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);
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;
status_t pgw_context_init()
{
int i;
d_assert(context_initiaized == 0, return CORE_ERROR,
"PGW context already has been initialized");
@ -70,9 +58,6 @@ status_t pgw_context_init()
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();
context_initiaized = 1;
@ -82,8 +67,6 @@ status_t pgw_context_init()
status_t pgw_context_final()
{
int i;
d_assert(context_initiaized == 1, return CORE_ERROR,
"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",
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_subnet_remove_all();
@ -518,8 +488,6 @@ status_t pgw_context_parse_config()
const char *apn = NULL;
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) ==
YAML_MAPPING_NODE)
{
@ -575,12 +543,6 @@ status_t pgw_context_parse_config()
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(
ipstr, mask_or_numbits, apn, dev);
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 rv;
int i, j;
int 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;
ipsubnet_t ipaddr, ipsub;
c_uint32_t prefixlen;
c_uint32_t mask_count;
c_uint32_t broadcast[4];
rv = core_ipsubnet(&ipaddr, self.ue_pool[i].ipstr, NULL);
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 (subnet->family == AF_INET)
{
if (prefixlen == 32)
if (subnet->prefixlen == 32)
mask_count = 1;
else if (prefixlen < 32)
mask_count = (0xffffffff >> prefixlen) + 1;
else if (subnet->prefixlen < 32)
mask_count = (0xffffffff >> subnet->prefixlen) + 1;
else
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;
else if (prefixlen > 96 && prefixlen < 128)
mask_count = (0xffffffff >> (prefixlen - 96)) + 1;
else if (prefixlen <= 96)
else if (subnet->prefixlen > 96 && subnet->prefixlen < 128)
mask_count = (0xffffffff >> (subnet->prefixlen - 96)) + 1;
else if (subnet->prefixlen <= 96)
mask_count = 0xffffffff;
else
d_assert(0, return CORE_ERROR,);
}
else
d_assert(0, return CORE_ERROR,);
self.ue_pool[i].family = ipsub.family;
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++)
@ -1210,128 +1159,117 @@ status_t pgw_ue_pool_generate()
int maxbytes = 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,);
memset(ue_ip, 0, sizeof *ue_ip);
if (ipsub.family == AF_INET)
if (subnet->family == AF_INET)
{
maxbytes = 4;
lastindex = 0;
}
else if (ipsub.family == AF_INET6)
else if (subnet->family == AF_INET6)
{
maxbytes = 16;
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->subnet = subnet;
/* 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 */
if (memcmp(ue_ip->addr, broadcast, maxbytes) == 0) continue;
/* 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++;
}
ue_ip_pool[i].size = ue_ip_pool[i].avail = index;
subnet->pool.size = subnet->pool.avail = index;
}
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;
c_uint8_t pool_index = INVALID_POOL_INDEX;
pgw_subnet_t *subnet = NULL;
d_assert(apn, return INVALID_POOL_INDEX,);
d_assert(family == AF_INET || family == AF_INET6,
return INVALID_POOL_INDEX,);
d_assert(apn, return NULL,);
d_assert(family == AF_INET || family == AF_INET6, return NULL,);
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 &&
strcmp(self.ue_pool[i].apn, apn) == 0 &&
pool_avail(&ue_ip_pool[i]))
if (subnet->family == family && strcmp(subnet->apn, apn) == 0 &&
pool_avail(&subnet->pool))
{
pool_index = i;
break;
return subnet;
}
}
}
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 &&
pool_avail(&ue_ip_pool[i]))
{
pool_index = i;
break;
}
return subnet;
}
}
}
if (pool_index == INVALID_POOL_INDEX)
{
if (subnet == NULL)
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)
{
c_uint8_t pool_index = INVALID_POOL_INDEX;
pgw_subnet_t *subnet = NULL;
pgw_ue_ip_t *ue_ip = NULL;
d_assert(apn, return NULL,);
pool_index = find_ue_pool_index(family, apn);
d_assert(pool_index < MAX_NUM_OF_UE_POOL, return NULL,);
subnet = find_subnet(family, apn);
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,);
ue_ip->index = pool_index;
return 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,);
pool_index = ue_ip->index;
subnet = ue_ip->subnet;
d_assert(pool_index < MAX_NUM_OF_UE_POOL, return CORE_ERROR,);
pool_free_node(&ue_ip_pool[pool_index], ue_ip);
d_assert(subnet, return CORE_ERROR,);
pool_free_node(&subnet->pool, ue_ip);
return CORE_OK;
}
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(index < MAX_NUM_OF_UE_POOL, return CORE_ERROR,);
d_assert(pgw_self()->ue_pool[index].mask_or_numbits,
return CORE_ERROR,);
return atoi(pgw_self()->ue_pool[index].mask_or_numbits);
d_assert(ue_ip, return -1,);
subnet = ue_ip->subnet;
d_assert(subnet, return -1,);
return subnet->prefixlen;
}
pgw_dev_t *pgw_dev_add(const char *ifname)
@ -1436,6 +1374,11 @@ pgw_subnet_t *pgw_subnet_add(
if (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);
return subnet;
@ -1446,6 +1389,16 @@ status_t pgw_subnet_remove(pgw_subnet_t *subnet)
d_assert(subnet, return CORE_ERROR, "Null param");
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);
return CORE_OK;

View File

@ -45,23 +45,10 @@ typedef struct _pgw_context_t {
sock_id tun_sock; /* PGW Tun Interace for UE */
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
const char *dns[2]; /* Primary/Secondanry */
const char *dns6[2]; /* Primary/Secondanry */
const char *dns[MAX_NUM_OF_DNS]; /* Primary/Secondanry */
const char *dns6[MAX_NUM_OF_DNS]; /* Primary/Secondanry */
list_t sgw_s5c_list; /* SGW GTPC 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) */
} 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 {
lnode_t node;
@ -85,16 +80,21 @@ typedef struct _pgw_subnet_t {
ipsubnet_t sub; /* Subnet : cafe::0/64 */
ipsubnet_t gw; /* Gateway : cafe::1 */
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_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 {
lnode_t node; /**< A node of list_t */
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 rv;
#if 0
int i;
#endif
int rc;
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
* Note that Linux will skip this configuration */
#if 0
for (i = 0; i < pgw_self()->num_of_ue_pool; i++)
{
rc = tun_set_ip(pgw_self()->tun_sock,
@ -226,6 +229,7 @@ status_t pgw_gtp_open()
return CORE_ERROR;
}
}
#endif
rc = sock_register(pgw_self()->tun_sock, _gtpv1_tun_recv_cb, NULL);
if (rc != 0)