Tun IPv4 is done

This commit is contained in:
Sukchan Lee 2017-12-13 12:20:02 +09:00
parent 3fc397c9f2
commit 6cd9e965a1
7 changed files with 76 additions and 283 deletions

View File

@ -198,8 +198,8 @@ CORE_DECLARE(int) core_sctp_recvmsg(sock_id id, void *msg, size_t len,
*/
CORE_DECLARE(status_t) tun_open(sock_id *new,
char *ifname, int is_tap);
CORE_DECLARE(status_t) tun_set_ipv4(sock_id id,
c_uint32_t ip_addr, c_uint8_t bits);
CORE_DECLARE(status_t) tun_set_ip(sock_id id,
const char *ipstr, const char *mask_or_numbits);
/*
* Send/Recv

View File

@ -79,7 +79,7 @@ cleanup:
#endif
}
status_t tun_set_ipv4(sock_id id, c_uint32_t ip_addr, c_uint8_t bits)
static status_t tun_set_ipv4(sock_id id, c_uint32_t ip_addr, c_uint8_t bits)
{
#if LINUX != 1
sock_t *sock = NULL;
@ -187,3 +187,28 @@ status_t tun_set_ipv4(sock_id id, c_uint32_t ip_addr, c_uint8_t bits)
return 0;
}
status_t tun_set_ip(sock_id id, const char *ipstr, const char *mask_or_numbits)
{
ipsubnet_t ipsub;
status_t rv;
d_assert(id, return CORE_ERROR,);
d_assert(ipstr, return CORE_ERROR,);
d_assert(mask_or_numbits, return CORE_ERROR,);
rv = core_ipsubnet(&ipsub, ipstr, NULL);
d_assert(rv == CORE_OK, return CORE_ERROR,);
if (ipsub.family == AF_INET)
{
rv = tun_set_ipv4(id, ipsub.sub[0], atoi(mask_or_numbits));
}
else
{
d_warn("Not support : %d\n", ipsub.family);
rv = CORE_OK;
}
return rv;
}

View File

@ -176,12 +176,6 @@ static status_t pgw_context_validation()
context_self()->config.path);
return CORE_ERROR;
}
if (self.num_of_ue_network == 0)
{
d_error("No pgw.pdn.addr in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.dns.primary == 0)
{
d_error("No pgw.dns in '%s'",
@ -593,116 +587,6 @@ status_t pgw_context_parse_config()
} while(yaml_iter_type(&ue_pool_array) ==
YAML_SEQUENCE_NODE);
}
else if (!strcmp(pgw_key, "ue_network"))
{
yaml_iter_t ue_network_array, ue_network_iter;
yaml_iter_recurse(&pgw_iter, &ue_network_array);
do
{
c_uint32_t addr = 0;
c_uint8_t bits = 0;
const char *dev = NULL;
const char *apn = NULL;
d_assert(self.num_of_ue_network <=
MAX_NUM_OF_UE_NETWORK, return CORE_ERROR,);
if (yaml_iter_type(&ue_network_array) ==
YAML_MAPPING_NODE)
{
memcpy(&ue_network_iter, &ue_network_array,
sizeof(yaml_iter_t));
}
else if (yaml_iter_type(&ue_network_array) ==
YAML_SEQUENCE_NODE)
{
if (!yaml_iter_next(&ue_network_array))
break;
yaml_iter_recurse(&ue_network_array,
&ue_network_iter);
}
else if (yaml_iter_type(&ue_network_array) ==
YAML_SCALAR_NODE)
{
break;
}
else
d_assert(0, return CORE_ERROR,);
while(yaml_iter_next(&ue_network_iter))
{
const char *ue_network_key =
yaml_iter_key(&ue_network_iter);
d_assert(ue_network_key,
return CORE_ERROR,);
if (!strcmp(ue_network_key, "addr"))
{
yaml_iter_t addr_iter;
yaml_iter_recurse(&ue_network_iter, &addr_iter);
d_assert(yaml_iter_type(&addr_iter) !=
YAML_MAPPING_NODE, return CORE_ERROR,);
do
{
char *v = NULL;
#if 0
d_assert(ue_network->num_of_addr <=
MAX_NUM_OF_PDN_ADDR,
return CORE_ERROR,);
#endif
if (yaml_iter_type(&addr_iter) ==
YAML_SEQUENCE_NODE)
{
if (!yaml_iter_next(&addr_iter))
break;
}
v = (char *)yaml_iter_value(&addr_iter);
if (v)
{
char *str = strsep(&v, "/");
if (str)
{
addr = inet_addr(str);
bits = atoi(v);
}
}
} while(
yaml_iter_type(&addr_iter) ==
YAML_SEQUENCE_NODE);
}
else if (!strcmp(ue_network_key, "dev"))
{
dev = yaml_iter_value(&ue_network_iter);
}
else if (!strcmp(ue_network_key, "apn"))
{
apn = yaml_iter_value(&ue_network_iter);
d_warn("Not implemented apn=%s", apn);
}
else
d_warn("unknown key `%s`", ue_network_key);
}
if (addr && bits)
{
self.ue_network[self.num_of_ue_network].ipv4.addr =
addr;
self.ue_network[self.num_of_ue_network].ipv4.bits =
bits;
self.ue_network[self.num_of_ue_network].if_name =
dev;
self.num_of_ue_network++;
}
else
{
d_warn("Ignore ue_network : addr(0x%x), bits(%d)",
addr, bits);
}
} while(yaml_iter_type(&ue_network_array) ==
YAML_SEQUENCE_NODE);
}
else if (!strcmp(pgw_key, "dns"))
{
int count = 0;
@ -1444,86 +1328,6 @@ pgw_pf_t* pgw_pf_next(pgw_pf_t *pf)
return list_next(pf);
}
status_t pgw_ip_pool_generate()
{
int i, j;
int pool_index = 0;
for (i = 0; i < self.num_of_ue_network; i++)
{
c_uint32_t mask =
htonl(0xffffffff << (32 - self.ue_network[i].ipv4.bits));
c_uint32_t prefix = self.ue_network[i].ipv4.addr & mask;
#if 1 /* Update IP assign rule from bradon's comment */
c_uint32_t broadcast = prefix + ~mask;
for (j = 1; j < (0xffffffff >> self.ue_network[i].ipv4.bits) &&
pool_index < MAX_POOL_OF_SESS; j++)
{
pgw_ip_pool_t *ip_pool = &pgw_ip_pool_pool.pool[pool_index];
ip_pool->ue_addr = prefix + htonl(j);
/* Exclude Network Address */
if (ip_pool->ue_addr == prefix) continue;
/* Exclude Broadcast Address */
if (ip_pool->ue_addr == broadcast) continue;
/* Exclude TUN IP Address */
if (ip_pool->ue_addr == self.ue_network[i].ipv4.addr) continue;
pool_index++;
}
#else /* Deprecated */
/* Exclude X.X.X.0, X.X.X.255 addresses from ip pool */
c_uint32_t exclude_mask[] = { 0, 255 };
for (j = 1; j < (0xffffffff >> self.ip_pool[i].mask) &&
pool_index < MAX_NUM_OF_SESS; j++)
{
int exclude = 0;
pgw_ip_pool_t *ip_pool = &pgw_ip_pool_pool.pool[pool_index];
ip_pool->ue_addr = prefix + htonl(j);
for (k = 0; k < sizeof(exclude_mask)/sizeof(exclude_mask[0]); k++)
{
if ((htonl(ip_pool->ue_addr) & 0x000000ff) == exclude_mask[k])
{
exclude = 1;
}
}
if (exclude)
{
continue;
}
pool_index++;
}
#endif
}
return CORE_OK;
}
pgw_ip_pool_t* pgw_ip_pool_alloc()
{
pgw_ip_pool_t *ip_pool = NULL;
pool_alloc_node(&pgw_ip_pool_pool, &ip_pool);
d_assert(ip_pool, return NULL, "IP Pool context allocation failed");
list_append(&self.ip_pool_list, ip_pool);
return ip_pool;
}
status_t pgw_ip_pool_free(pgw_ip_pool_t *ip_pool)
{
list_remove(&self.ip_pool_list, ip_pool);
pool_free_node(&pgw_ip_pool_pool, ip_pool);
return CORE_OK;
}
status_t pgw_ue_pool_generate()
{
status_t rv;

View File

@ -12,7 +12,6 @@
#include "gtp_types.h"
#include "gtp_message.h"
#define MAX_NUM_OF_UE_NETWORK 16
#define MAX_NUM_OF_UE_POOL 16
#ifdef __cplusplus
@ -50,16 +49,6 @@ typedef struct _pgw_context_t {
} ue_pool[MAX_NUM_OF_UE_POOL];
c_uint8_t num_of_ue_pool;
struct {
sock_id tun_link; /* PGW Tun Interace for U-plane */
const char *if_name;
struct {
c_uint32_t addr;
c_uint8_t bits;
} ipv4;
} ue_network[MAX_NUM_OF_UE_NETWORK];
c_uint8_t num_of_ue_network;
struct {
c_uint32_t primary;
c_uint32_t secondary;
@ -219,10 +208,6 @@ CORE_DECLARE(pgw_pf_t*) pgw_pf_find_by_id(
CORE_DECLARE(pgw_pf_t*) pgw_pf_first(pgw_bearer_t *bearer);
CORE_DECLARE(pgw_pf_t*) pgw_pf_next(pgw_pf_t *pf);
CORE_DECLARE(status_t ) pgw_ip_pool_generate();
CORE_DECLARE(pgw_ip_pool_t*) pgw_ip_pool_alloc();
CORE_DECLARE(status_t ) pgw_ip_pool_free(pgw_ip_pool_t *ip_pool);
CORE_DECLARE(status_t ) pgw_ue_pool_generate();
CORE_DECLARE(pgw_ue_ip_t *) pgw_ue_ip_alloc(int family, const char *apn);
CORE_DECLARE(status_t) pgw_ue_ip_free(pgw_ue_ip_t *ip);

View File

@ -136,8 +136,7 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data)
return -1;
}
if (sock_write(pgw_self()->ue_network[(c_uintptr_t)data].tun_link,
pkbuf->payload, pkbuf->len) <= 0)
if (sock_write(pgw_self()->tun_sock, pkbuf->payload, pkbuf->len) <= 0)
{
d_error("Can not send packets to tuntap");
}
@ -175,67 +174,59 @@ status_t pgw_gtp_open()
d_assert(pgw_self()->gtpu_addr || pgw_self()->gtpu_addr6,
return CORE_ERROR, "No GTP Server");
for (i = 0; i < pgw_self()->num_of_ue_network; i++)
/* NOTE : tun device can be created via following command.
*
* $ sudo ip tuntap add name pgwtun mode tun
*
* Also, before running pgw, assign the one IP from IP pool of UE
* to pgwtun. The IP should not be assigned to UE
*
* $ sudo ifconfig pgwtun 45.45.0.1/16 up
*
*/
/* Open Tun interface */
rc = tun_open(&pgw_self()->tun_sock, (char *)pgw_self()->tun_ifname, 0);
if (rc != 0)
{
/* NOTE : tun device can be created via following command.
*
* $ sudo ip tuntap add name pgwtun mode tun
*
* Also, before running pgw, assign the one IP from IP pool of UE
* to pgwtun. The IP should not be assigned to UE
*
* $ sudo ifconfig pgwtun 45.45.0.1/16 up
*
*/
d_error("Can not open tun(dev : %s)", pgw_self()->tun_ifname);
return CORE_ERROR;
}
/* Open Tun interface */
rc = tun_open(&pgw_self()->ue_network[i].tun_link,
(char *)pgw_self()->ue_network[i].if_name, 0);
/*
* On Linux, it is possible to create a persistent tun/tap
* interface which will continue to exist even if nextepc quit,
* although this is normally not required.
* It can be useful to set up a tun/tap interface owned
* by a non-root user, so nextepc can be started without
* needing any root privileges at all.
*/
/* Set P-to-P IP address with Netmask
* Note that Linux will skip this configuration */
for (i = 0; i < pgw_self()->num_of_ue_pool; i++)
{
rc = tun_set_ip(pgw_self()->tun_sock,
pgw_self()->ue_pool[i].ipstr,
pgw_self()->ue_pool[i].mask_or_numbits);
if (rc != 0)
{
d_error("Can not open tun(dev : %s)",
pgw_self()->ue_network[i].if_name);
d_error("Can not configure tun(dev : %s for %s/%s)",
pgw_self()->tun_ifname,
pgw_self()->ue_pool[i].ipstr,
pgw_self()->ue_pool[i].mask_or_numbits);
return CORE_ERROR;
}
}
/*
* On Linux, it is possible to create a persistent tun/tap
* interface which will continue to exist even if nextepc quit,
* although this is normally not required.
* It can be useful to set up a tun/tap interface owned
* by a non-root user, so nextepc can be started without
* needing any root privileges at all.
*/
/* Set P-to-P IP address with Netmask
* Note that Linux will skip this configuration */
rc = tun_set_ipv4(pgw_self()->ue_network[i].tun_link,
pgw_self()->ue_network[i].ipv4.addr,
pgw_self()->ue_network[i].ipv4.bits);
if (rc != 0)
{
#if 0 /* ADDR */
d_error("Can not configure tun(dev : %s for %s/%d)",
pgw_self()->ue_network[i].if_name,
INET_NTOP(&pgw_self()->ue_network[i].ipv4.addr, buf),
pgw_self()->ue_network[i].ipv4.bits);
#else
d_error("Can not configure tun(dev : %s for /%d)",
pgw_self()->ue_network[i].if_name,
pgw_self()->ue_network[i].ipv4.bits);
#endif
return CORE_ERROR;
}
rc = sock_register(pgw_self()->ue_network[i].tun_link,
_gtpv1_tun_recv_cb, (void *)(c_uintptr_t)i);
if (rc != 0)
{
d_error("Can not register tun(dev : %s)",
pgw_self()->ue_network[i].if_name);
sock_delete(pgw_self()->ue_network[i].tun_link);
return CORE_ERROR;
}
rc = sock_register(pgw_self()->tun_sock, _gtpv1_tun_recv_cb, NULL);
if (rc != 0)
{
d_error("Can not register tun(dev : %s)",
pgw_self()->tun_ifname);
sock_delete(pgw_self()->tun_sock);
return CORE_ERROR;
}
return CORE_OK;
@ -243,18 +234,13 @@ status_t pgw_gtp_open()
status_t pgw_gtp_close()
{
int i;
sock_delete_list(&pgw_self()->gtpc_list);
sock_delete_list(&pgw_self()->gtpc_list6);
sock_delete_list(&pgw_self()->gtpu_list);
sock_delete_list(&pgw_self()->gtpu_list6);
for (i = 0; i < pgw_self()->num_of_ue_network; i++)
{
sock_delete(pgw_self()->ue_network[i].tun_link);
}
sock_delete(pgw_self()->tun_sock);
return CORE_OK;
}

View File

@ -33,9 +33,6 @@ status_t pgw_initialize()
rv = pgw_ue_pool_generate();
if (rv != CORE_OK) return rv;
rv = pgw_ip_pool_generate();
if (rv != CORE_OK) return rv;
ret = pgw_fd_init();
if (ret != 0) return CORE_ERROR;

View File

@ -324,10 +324,6 @@ pgw:
- addr: 45.45.0.1/16
- addr: cafe::1/64
ue_network:
addr: 45.45.0.1/16
dev: pgwtun
#
# <Domain Name Server>
#