subnet is tested

This commit is contained in:
Sukchan Lee 2017-12-17 05:50:24 +00:00
parent 0cf2319b9c
commit 60804c79d6
3 changed files with 91 additions and 134 deletions

View File

@ -30,22 +30,10 @@ index_declare(pgw_bearer_pool, pgw_bearer_t, MAX_POOL_OF_BEARER);
pool_declare(pgw_pf_pool, pgw_pf_t, MAX_POOL_OF_PF); pool_declare(pgw_pf_pool, pgw_pf_t, MAX_POOL_OF_PF);
typedef struct _ue_pool_t {
int head, tail;
int size, avail;
mutex_id mut;
pgw_ue_ip_t *free[MAX_POOL_OF_SESS], pool[MAX_POOL_OF_SESS];
} ue_pool_t;
#define INVALID_POOL_INDEX MAX_NUM_OF_UE_POOL
static ue_pool_t ue_ip_pool[MAX_NUM_OF_UE_POOL];
static int context_initiaized = 0; static int context_initiaized = 0;
status_t pgw_context_init() status_t pgw_context_init()
{ {
int i;
d_assert(context_initiaized == 0, return CORE_ERROR, d_assert(context_initiaized == 0, return CORE_ERROR,
"PGW context already has been initialized"); "PGW context already has been initialized");
@ -70,9 +58,6 @@ status_t pgw_context_init()
pool_init(&pgw_pf_pool, MAX_POOL_OF_PF); pool_init(&pgw_pf_pool, MAX_POOL_OF_PF);
for (i = 0; i < MAX_NUM_OF_UE_POOL; i++)
pool_init(&ue_ip_pool[i], MAX_POOL_OF_UE);
self.sess_hash = hash_make(); self.sess_hash = hash_make();
context_initiaized = 1; context_initiaized = 1;
@ -82,8 +67,6 @@ status_t pgw_context_init()
status_t pgw_context_final() status_t pgw_context_final()
{ {
int i;
d_assert(context_initiaized == 1, return CORE_ERROR, d_assert(context_initiaized == 1, return CORE_ERROR,
"PGW context already has been finalized"); "PGW context already has been finalized");
@ -98,19 +81,6 @@ status_t pgw_context_final()
d_trace(3, "%d not freed in pgw_sess_pool[%d] in PGW-Context\n", d_trace(3, "%d not freed in pgw_sess_pool[%d] in PGW-Context\n",
index_used(&pgw_sess_pool), index_size(&pgw_sess_pool)); index_used(&pgw_sess_pool), index_size(&pgw_sess_pool));
for (i = 0; i < MAX_NUM_OF_UE_POOL; i++)
{
if (pool_used(&ue_ip_pool[i]))
{
d_warn("[%d] %d not freed in ue_ip_pool[%d] in PGW-Context",
i, pool_used(&ue_ip_pool[i]), index_size(&ue_ip_pool[i]));
}
d_trace(3, "[%d] %d not freed in ue_ip_pool[%d] in PGW-Context\n",
i, pool_used(&ue_ip_pool[i]), index_size(&ue_ip_pool[i]));
pool_final(&ue_ip_pool[i]);
}
pgw_dev_remove_all(); pgw_dev_remove_all();
pgw_subnet_remove_all(); pgw_subnet_remove_all();
@ -518,8 +488,6 @@ status_t pgw_context_parse_config()
const char *apn = NULL; const char *apn = NULL;
const char *dev = self.tun_ifname; const char *dev = self.tun_ifname;
d_assert(self.num_of_ue_pool <=
MAX_NUM_OF_UE_POOL, return CORE_ERROR,);
if (yaml_iter_type(&ue_pool_array) == if (yaml_iter_type(&ue_pool_array) ==
YAML_MAPPING_NODE) YAML_MAPPING_NODE)
{ {
@ -575,12 +543,6 @@ status_t pgw_context_parse_config()
if (ipstr && mask_or_numbits) if (ipstr && mask_or_numbits)
{ {
self.ue_pool[self.num_of_ue_pool].ipstr = ipstr;
self.ue_pool[self.num_of_ue_pool].mask_or_numbits =
mask_or_numbits;
self.ue_pool[self.num_of_ue_pool].apn = apn;
self.num_of_ue_pool++;
subnet = pgw_subnet_add( subnet = pgw_subnet_add(
ipstr, mask_or_numbits, apn, dev); ipstr, mask_or_numbits, apn, dev);
d_assert(subnet, return CORE_ERROR,); d_assert(subnet, return CORE_ERROR,);
@ -1154,54 +1116,41 @@ pgw_pf_t* pgw_pf_next(pgw_pf_t *pf)
status_t pgw_ue_pool_generate() status_t pgw_ue_pool_generate()
{ {
status_t rv; int j;
int i, j; pgw_subnet_t *subnet = NULL;
for (i = 0; i < self.num_of_ue_pool; i++) for (subnet = pgw_subnet_first(); subnet; subnet = pgw_subnet_next(subnet))
{ {
int index = 0; int index = 0;
ipsubnet_t ipaddr, ipsub;
c_uint32_t prefixlen;
c_uint32_t mask_count; c_uint32_t mask_count;
c_uint32_t broadcast[4]; c_uint32_t broadcast[4];
rv = core_ipsubnet(&ipaddr, self.ue_pool[i].ipstr, NULL); if (subnet->family == AF_INET)
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = core_ipsubnet(&ipsub,
self.ue_pool[i].ipstr, self.ue_pool[i].mask_or_numbits);
d_assert(rv == CORE_OK, return CORE_ERROR,);
d_assert(self.ue_pool[i].mask_or_numbits, return CORE_ERROR,);
prefixlen = atoi(self.ue_pool[i].mask_or_numbits);
if (ipsub.family == AF_INET)
{ {
if (prefixlen == 32) if (subnet->prefixlen == 32)
mask_count = 1; mask_count = 1;
else if (prefixlen < 32) else if (subnet->prefixlen < 32)
mask_count = (0xffffffff >> prefixlen) + 1; mask_count = (0xffffffff >> subnet->prefixlen) + 1;
else else
d_assert(0, return CORE_ERROR,); d_assert(0, return CORE_ERROR,);
} }
else if (ipsub.family == AF_INET6) else if (subnet->family == AF_INET6)
{ {
if (prefixlen == 128) if (subnet->prefixlen == 128)
mask_count = 1; mask_count = 1;
else if (prefixlen > 96 && prefixlen < 128) else if (subnet->prefixlen > 96 && subnet->prefixlen < 128)
mask_count = (0xffffffff >> (prefixlen - 96)) + 1; mask_count = (0xffffffff >> (subnet->prefixlen - 96)) + 1;
else if (prefixlen <= 96) else if (subnet->prefixlen <= 96)
mask_count = 0xffffffff; mask_count = 0xffffffff;
else else
d_assert(0, return CORE_ERROR,); d_assert(0, return CORE_ERROR,);
} }
else else
d_assert(0, return CORE_ERROR,); d_assert(0, return CORE_ERROR,);
self.ue_pool[i].family = ipsub.family;
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
{ {
broadcast[j] = ipsub.sub[j] + ~ipsub.mask[j]; broadcast[j] = subnet->sub.sub[j] + ~subnet->sub.mask[j];
} }
for (j = 0; j < mask_count && index < MAX_POOL_OF_SESS; j++) for (j = 0; j < mask_count && index < MAX_POOL_OF_SESS; j++)
@ -1210,128 +1159,117 @@ status_t pgw_ue_pool_generate()
int maxbytes = 0; int maxbytes = 0;
int lastindex = 0; int lastindex = 0;
ue_ip = &ue_ip_pool[i].pool[index]; ue_ip = &subnet->pool.pool[index];
d_assert(ue_ip, return CORE_ERROR,); d_assert(ue_ip, return CORE_ERROR,);
memset(ue_ip, 0, sizeof *ue_ip); memset(ue_ip, 0, sizeof *ue_ip);
if (ipsub.family == AF_INET) if (subnet->family == AF_INET)
{ {
maxbytes = 4; maxbytes = 4;
lastindex = 0; lastindex = 0;
} }
else if (ipsub.family == AF_INET6) else if (subnet->family == AF_INET6)
{ {
maxbytes = 16; maxbytes = 16;
lastindex = 3; lastindex = 3;
} }
memcpy(ue_ip->addr, ipsub.sub, maxbytes); memcpy(ue_ip->addr, subnet->sub.sub, maxbytes);
ue_ip->addr[lastindex] += htonl(j); ue_ip->addr[lastindex] += htonl(j);
ue_ip->subnet = subnet;
/* Exclude Network Address */ /* Exclude Network Address */
if (memcmp(ue_ip->addr, ipsub.sub, maxbytes) == 0) continue; if (memcmp(ue_ip->addr, subnet->sub.sub, maxbytes) == 0) continue;
/* Exclude Broadcast Address */ /* Exclude Broadcast Address */
if (memcmp(ue_ip->addr, broadcast, maxbytes) == 0) continue; if (memcmp(ue_ip->addr, broadcast, maxbytes) == 0) continue;
/* Exclude TUN IP Address */ /* Exclude TUN IP Address */
if (memcmp(ue_ip->addr, ipaddr.sub, maxbytes) == 0) continue; if (memcmp(ue_ip->addr, subnet->gw.sub, maxbytes) == 0) continue;
index++; index++;
} }
ue_ip_pool[i].size = ue_ip_pool[i].avail = index; subnet->pool.size = subnet->pool.avail = index;
} }
return CORE_OK; return CORE_OK;
} }
static c_uint8_t find_ue_pool_index(int family, const char *apn) static pgw_subnet_t *find_subnet(int family, const char *apn)
{ {
int i; pgw_subnet_t *subnet = NULL;
c_uint8_t pool_index = INVALID_POOL_INDEX;
d_assert(apn, return INVALID_POOL_INDEX,); d_assert(apn, return NULL,);
d_assert(family == AF_INET || family == AF_INET6, d_assert(family == AF_INET || family == AF_INET6, return NULL,);
return INVALID_POOL_INDEX,);
for (i = 0; i < self.num_of_ue_pool; i++) for (subnet = pgw_subnet_first(); subnet; subnet = pgw_subnet_next(subnet))
{ {
if (self.ue_pool[i].apn) if (strlen(subnet->apn))
{ {
if (self.ue_pool[i].family == family && if (subnet->family == family && strcmp(subnet->apn, apn) == 0 &&
strcmp(self.ue_pool[i].apn, apn) == 0 && pool_avail(&subnet->pool))
pool_avail(&ue_ip_pool[i]))
{ {
pool_index = i; return subnet;
break;
} }
} }
} }
if (pool_index == INVALID_POOL_INDEX) for (subnet = pgw_subnet_first(); subnet; subnet = pgw_subnet_next(subnet))
{ {
for (i = 0; i < self.num_of_ue_pool; i++) if (strlen(subnet->apn) == 0)
{ {
if (self.ue_pool[i].apn == NULL) if (subnet->family == family &&
pool_avail(&subnet->pool))
{ {
if (self.ue_pool[i].family == family && return subnet;
pool_avail(&ue_ip_pool[i]))
{
pool_index = i;
break;
}
} }
} }
} }
if (pool_index == INVALID_POOL_INDEX) if (subnet == NULL)
{
d_error("CHECK CONFIGURATION: Cannot find UE Pool"); d_error("CHECK CONFIGURATION: Cannot find UE Pool");
return INVALID_POOL_INDEX;
}
return pool_index; return subnet;
} }
pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn) pgw_ue_ip_t *pgw_ue_ip_alloc(int family, const char *apn)
{ {
c_uint8_t pool_index = INVALID_POOL_INDEX; pgw_subnet_t *subnet = NULL;
pgw_ue_ip_t *ue_ip = NULL; pgw_ue_ip_t *ue_ip = NULL;
d_assert(apn, return NULL,); d_assert(apn, return NULL,);
pool_index = find_ue_pool_index(family, apn); subnet = find_subnet(family, apn);
d_assert(pool_index < MAX_NUM_OF_UE_POOL, return NULL,); d_assert(subnet, return NULL,);
pool_alloc_node(&ue_ip_pool[pool_index], &ue_ip); pool_alloc_node(&subnet->pool, &ue_ip);
d_assert(ue_ip, return NULL,); d_assert(ue_ip, return NULL,);
ue_ip->index = pool_index;
return ue_ip; return ue_ip;
} }
status_t pgw_ue_ip_free(pgw_ue_ip_t *ue_ip) status_t pgw_ue_ip_free(pgw_ue_ip_t *ue_ip)
{ {
c_uint8_t pool_index; pgw_subnet_t *subnet = NULL;
d_assert(ue_ip, return CORE_ERROR,); d_assert(ue_ip, return CORE_ERROR,);
pool_index = ue_ip->index; subnet = ue_ip->subnet;
d_assert(pool_index < MAX_NUM_OF_UE_POOL, return CORE_ERROR,); d_assert(subnet, return CORE_ERROR,);
pool_free_node(&ue_ip_pool[pool_index], ue_ip); pool_free_node(&subnet->pool, ue_ip);
return CORE_OK; return CORE_OK;
} }
c_uint8_t pgw_ue_ip_prefixlen(pgw_ue_ip_t *ue_ip) c_uint8_t pgw_ue_ip_prefixlen(pgw_ue_ip_t *ue_ip)
{ {
d_assert(ue_ip, return CORE_ERROR,); pgw_subnet_t *subnet = NULL;
c_uint8_t index = ue_ip->index; d_assert(ue_ip, return -1,);
d_assert(index < MAX_NUM_OF_UE_POOL, return CORE_ERROR,); subnet = ue_ip->subnet;
d_assert(pgw_self()->ue_pool[index].mask_or_numbits, d_assert(subnet, return -1,);
return CORE_ERROR,);
return atoi(pgw_self()->ue_pool[index].mask_or_numbits); return subnet->prefixlen;
} }
pgw_dev_t *pgw_dev_add(const char *ifname) pgw_dev_t *pgw_dev_add(const char *ifname)
@ -1436,6 +1374,11 @@ pgw_subnet_t *pgw_subnet_add(
if (apn) if (apn)
strcpy(subnet->apn, apn); strcpy(subnet->apn, apn);
subnet->family = subnet->gw.family;
subnet->prefixlen = atoi(mask_or_numbits);
pool_init(&subnet->pool, MAX_POOL_OF_UE);
list_append(&self.subnet_list, subnet); list_append(&self.subnet_list, subnet);
return subnet; return subnet;
@ -1446,6 +1389,16 @@ status_t pgw_subnet_remove(pgw_subnet_t *subnet)
d_assert(subnet, return CORE_ERROR, "Null param"); d_assert(subnet, return CORE_ERROR, "Null param");
list_remove(&self.subnet_list, subnet); list_remove(&self.subnet_list, subnet);
if (pool_used(&subnet->pool))
{
d_warn("%d not freed in ue_ip_pool[%d] in PGW-Context",
pool_used(&subnet->pool), pool_size(&subnet->pool));
}
d_trace(3, "%d not freed in ue_ip_pool[%d] in PGW-Context\n",
pool_used(&subnet->pool), pool_size(&subnet->pool));
pool_final(&subnet->pool);
pool_free_node(&pgw_subnet_pool, subnet); pool_free_node(&pgw_subnet_pool, subnet);
return CORE_OK; return CORE_OK;

View File

@ -45,23 +45,10 @@ typedef struct _pgw_context_t {
sock_id tun_sock; /* PGW Tun Interace for UE */ sock_id tun_sock; /* PGW Tun Interace for UE */
const char *tun_ifname; /* default : pgwtun */ const char *tun_ifname; /* default : pgwtun */
#define MAX_NUM_OF_UE_POOL 16
struct {
const char *ipstr; /* IP : "172.16.0.1", "cafe::1", ... */
const char *mask_or_numbits; /* MASK : "16, 64, ... */
const char *apn; /* APN : "internet", "volte", .. */
int family; /* AF_INET or AF_INET6 */
} ue_pool[MAX_NUM_OF_UE_POOL];
c_uint8_t num_of_ue_pool;
struct {
c_uint32_t primary;
c_uint32_t secondary;
} old_dns;
#define MAX_NUM_OF_DNS 2 #define MAX_NUM_OF_DNS 2
const char *dns[2]; /* Primary/Secondanry */ const char *dns[MAX_NUM_OF_DNS]; /* Primary/Secondanry */
const char *dns6[2]; /* Primary/Secondanry */ const char *dns6[MAX_NUM_OF_DNS]; /* Primary/Secondanry */
list_t sgw_s5c_list; /* SGW GTPC Node List */ list_t sgw_s5c_list; /* SGW GTPC Node List */
list_t sgw_s5u_list; /* SGW GTPU Node List */ list_t sgw_s5u_list; /* SGW GTPU Node List */
@ -70,6 +57,14 @@ typedef struct _pgw_context_t {
hash_t *sess_hash; /* hash table (IMSI+APN) */ hash_t *sess_hash; /* hash table (IMSI+APN) */
} pgw_context_t; } pgw_context_t;
typedef struct _pgw_subnet_t pgw_subnet_t;
typedef struct _pgw_ue_ip_t {
c_uint32_t addr[4];
/* Related Context */
pgw_subnet_t *subnet;
} pgw_ue_ip_t;
typedef struct _pgw_dev_t { typedef struct _pgw_dev_t {
lnode_t node; lnode_t node;
@ -85,16 +80,21 @@ typedef struct _pgw_subnet_t {
ipsubnet_t sub; /* Subnet : cafe::0/64 */ ipsubnet_t sub; /* Subnet : cafe::0/64 */
ipsubnet_t gw; /* Gateway : cafe::1 */ ipsubnet_t gw; /* Gateway : cafe::1 */
c_int8_t apn[MAX_APN_LEN]; /* APN : "internet", "volte", .. */ c_int8_t apn[MAX_APN_LEN]; /* APN : "internet", "volte", .. */
int family; /* AF_INET or AF_INET6 */
int family; /* AF_INET or AF_INET6 */
c_uint8_t prefixlen; /* prefixlen */
struct {
int head, tail;
int size, avail;
mutex_id mut;
pgw_ue_ip_t *free[MAX_POOL_OF_SESS], pool[MAX_POOL_OF_SESS];
} pool;
/* Related Context */
pgw_dev_t *dev; pgw_dev_t *dev;
} pgw_subnet_t; } pgw_subnet_t;
typedef struct _pgw_ue_ip_t {
c_uint8_t index; /* Pool index */
c_uint32_t addr[4];
} pgw_ue_ip_t;
typedef struct _pgw_sess_t { typedef struct _pgw_sess_t {
lnode_t node; /**< A node of list_t */ lnode_t node; /**< A node of list_t */
index_t index; /**< An index of this node */ index_t index; /**< An index of this node */

View File

@ -156,7 +156,9 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data)
status_t pgw_gtp_open() status_t pgw_gtp_open()
{ {
status_t rv; status_t rv;
#if 0
int i; int i;
#endif
int rc; int rc;
rv = gtp_server_list(&pgw_self()->gtpc_list, _gtpv2_c_recv_cb); rv = gtp_server_list(&pgw_self()->gtpc_list, _gtpv2_c_recv_cb);
@ -211,6 +213,7 @@ status_t pgw_gtp_open()
/* Set P-to-P IP address with Netmask /* Set P-to-P IP address with Netmask
* Note that Linux will skip this configuration */ * Note that Linux will skip this configuration */
#if 0
for (i = 0; i < pgw_self()->num_of_ue_pool; i++) for (i = 0; i < pgw_self()->num_of_ue_pool; i++)
{ {
rc = tun_set_ip(pgw_self()->tun_sock, rc = tun_set_ip(pgw_self()->tun_sock,
@ -226,6 +229,7 @@ status_t pgw_gtp_open()
return CORE_ERROR; return CORE_ERROR;
} }
} }
#endif
rc = sock_register(pgw_self()->tun_sock, _gtpv1_tun_recv_cb, NULL); rc = sock_register(pgw_self()->tun_sock, _gtpv1_tun_recv_cb, NULL);
if (rc != 0) if (rc != 0)