SGW/PGW GTP-U is added

This commit is contained in:
Sukchan Lee 2017-12-07 13:27:17 +09:00
parent f8f18eb6f5
commit 03a6bb7902
23 changed files with 484 additions and 368 deletions

View File

@ -31,6 +31,7 @@ extern "C" {
#define MAX_POOL_OF_TUNNEL (MAX_POOL_OF_BEARER * MAX_NUM_OF_TUNNEL)
#define MAX_POOL_OF_PF (MAX_POOL_OF_BEARER * MAX_NUM_OF_PF)
#define MAX_NUM_OF_HOSTNAME 16
#define MAX_NUM_OF_PCC_RULE 8
#define MAX_NUM_OF_FLOW 8 /* Num of Flow per PCC Rule */
#define MAX_NUM_OF_PACKET_FILTER 16 /* Num of Packet Filter per Bearer */

View File

@ -104,6 +104,7 @@ CORE_DECLARE(status_t) network_final(void);
*/
CORE_DECLARE(status_t) sock_create(sock_id *new);
CORE_DECLARE(status_t) sock_delete(sock_id id);
CORE_DECLARE(status_t) sock_delete_list(list_t *list);
CORE_DECLARE(status_t) sock_socket(
sock_id *id, int family, int type, int protocol);

View File

@ -90,6 +90,22 @@ status_t sock_delete(sock_id id)
return CORE_OK;
}
status_t sock_delete_list(list_t *list)
{
status_t rv;
sock_node_t *snode;
d_assert(list, return CORE_ERROR,);
for (snode = list_first(list); snode; snode = list_next(snode))
{
rv = sock_delete(snode->sock);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
return CORE_OK;
}
status_t sock_socket(sock_id *new, int family, int type, int protocol)
{
status_t rv;

View File

@ -94,7 +94,7 @@ status_t gtp_f_teid_to_sockaddr(
}
status_t gtp_sockaddr_to_f_teid(
c_sockaddr_t *addr, c_sockaddr_t *addr6, gtp_f_teid_t *f_teid, int *len)
c_sockaddr_t *addr, c_sockaddr_t *addr6, gtp_f_teid_t *f_teid)
{
d_assert(f_teid, return CORE_ERROR,);
@ -109,22 +109,66 @@ status_t gtp_sockaddr_to_f_teid(
f_teid->ip.both.addr = addr->sin.sin_addr.s_addr;
f_teid->ipv6 = 1;
memcpy(f_teid->ip.both.addr6, addr6->sin6.sin6_addr.s6_addr, IPV6_LEN);
*len = GTP_F_TEID_IPV4_AND_IPV6_LEN;
}
else if (addr)
{
f_teid->ipv4 = 1;
f_teid->ip.addr = addr->sin.sin_addr.s_addr;
*len = GTP_F_TEID_IPV4_LEN;
}
else if (addr6)
{
f_teid->ipv6 = 1;
memcpy(f_teid->ip.addr6, addr6->sin6.sin6_addr.s6_addr, IPV6_LEN);
*len = GTP_F_TEID_IPV6_LEN;
}
else
d_assert(0, return CORE_ERROR,);
return CORE_OK;
}
int gtp_f_teid_len(gtp_f_teid_t *f_teid)
{
int len = 0;
if (f_teid->ipv4 && f_teid->ipv6)
len = GTP_F_TEID_IPV4_AND_IPV6_LEN;
else if (f_teid->ipv4)
len = GTP_F_TEID_IPV4_LEN;
else if (f_teid->ipv6)
len = GTP_F_TEID_IPV6_LEN;
else
d_assert(0, return 0,);
return len;
}
gtp_f_teid_t *gtp_f_teid_copy(gtp_f_teid_t *dst, gtp_f_teid_t *src)
{
d_assert(src, return NULL,);
d_assert(dst, return NULL,);
memset(dst, 0, sizeof(gtp_f_teid_t));
dst->ipv4 = src->ipv4;
dst->ipv6 = src->ipv6;
dst->interface_type = 0;
dst->teid = 0;
if (dst->ipv4 && dst->ipv6)
{
dst->ip.both.addr = src->ip.both.addr;
memcpy(dst->ip.both.addr6, src->ip.both.addr6, IPV6_LEN);
}
else if (dst->ipv4)
{
dst->ip.addr = src->ip.addr;
}
else if (dst->ipv6)
{
memcpy(dst->ip.addr6, src->ip.addr6, IPV6_LEN);
}
else
d_assert(0, return NULL,);
return dst;
}

View File

@ -26,7 +26,10 @@ CORE_DECLARE(void) gtp_bearers_in_create_indirect_tunnel_response(
CORE_DECLARE(status_t) gtp_f_teid_to_sockaddr(
gtp_f_teid_t *f_teid, c_uint16_t port, c_sockaddr_t **list);
CORE_DECLARE(status_t) gtp_sockaddr_to_f_teid(
c_sockaddr_t *addr, c_sockaddr_t *addr6, gtp_f_teid_t *f_teid, int *len);
c_sockaddr_t *addr, c_sockaddr_t *addr6, gtp_f_teid_t *f_teid);
CORE_DECLARE(int) gtp_f_teid_len(gtp_f_teid_t *f_teid);
CORE_DECLARE(gtp_f_teid_t *) gtp_f_teid_copy(
gtp_f_teid_t *dst, gtp_f_teid_t *src);
#ifdef __cplusplus
}

View File

@ -116,42 +116,23 @@ status_t gtp_remove_all_nodes(list_t *list)
return CORE_OK;
}
static ip_t *gtp_node_ip(ip_t *ip, gtp_f_teid_t *f_teid)
{
d_assert(ip, return NULL,);
d_assert(f_teid, return NULL,);
memset(ip, 0, sizeof(ip_t));
if (f_teid->ipv4 && f_teid->ipv6)
{
ip->both.addr = f_teid->ip.both.addr;
memcpy(ip->both.addr6, f_teid->ip.both.addr6, IPV6_LEN);
}
else if (f_teid->ipv4)
{
ip->addr = f_teid->ip.addr;
}
else if (f_teid->ipv6)
{
memcpy(ip->addr6, f_teid->ip.addr6, IPV6_LEN);
}
else
d_assert(0, return NULL,);
return ip;
}
gtp_node_t* gtp_find_node(list_t *list, gtp_f_teid_t *f_teid)
{
gtp_node_t *node = NULL;
gtp_f_teid_t ip;
int len;
d_assert(list, return NULL,);
d_assert(f_teid, return NULL,);
len = gtp_f_teid_len(f_teid);
d_assert(len > 0, return NULL,);
d_assert(gtp_f_teid_copy(&ip, f_teid), return NULL,);
node = list_first(list);
while (node)
{
ip_t ip;
d_assert(gtp_node_ip(&ip, f_teid), return NULL,);
if (memcmp(&node->ip, &ip, sizeof(ip_t)) == 0)
if (memcmp(&node->f_teid, &ip, len) == 0)
break;
node = list_next(node);
@ -166,7 +147,6 @@ gtp_node_t *gtp_connect_node(list_t *list, gtp_f_teid_t *f_teid,
status_t rv;
gtp_node_t *node = NULL;
c_sockaddr_t *sa_list = NULL;
ip_t ip;
d_assert(list, return NULL,);
d_assert(f_teid, return NULL,);
@ -179,8 +159,7 @@ gtp_node_t *gtp_connect_node(list_t *list, gtp_f_teid_t *f_teid,
d_assert(rv == CORE_OK, return NULL,);
d_assert(node, return NULL,);
d_assert(gtp_node_ip(&ip, f_teid), return NULL,);
memcpy(&node->ip, &ip, sizeof(ip_t));
d_assert(gtp_f_teid_copy(&node->f_teid, f_teid), return NULL,);
core_freeaddrinfo(sa_list);

View File

@ -24,7 +24,7 @@ typedef struct _gtp_node_t {
lnode_t node; /* A node of list_t */
c_sockaddr_t *sa_list; /* Socket Address List */
ip_t ip; /* IPv4/IPv6 address */
gtp_f_teid_t f_teid; /* GTP F-TEID */
sock_id sock; /* Socket instance */

View File

@ -44,6 +44,39 @@ status_t gtp_client(gtp_node_t *gnode)
return CORE_OK;
}
status_t gtp_server_list(list_t *list, sock_handler handler)
{
status_t rv;
sock_node_t *snode = NULL;
d_assert(list, return CORE_ERROR,);
d_assert(handler, return CORE_ERROR,);
for (snode = list_first(list); snode; snode = list_next(snode))
{
rv = gtp_server(snode, handler);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
return CORE_OK;
}
c_sockaddr_t *gtp_local_addr_first(list_t *list)
{
sock_node_t *snode = NULL;
c_sockaddr_t *addr = NULL;
d_assert(list, return NULL,);
for (snode = list_first(list); snode; snode = list_next(snode))
{
addr = sock_local_addr(snode->sock);
if (addr) return addr;
}
return NULL;
}
status_t gtp_listen(sock_id *sock,
sock_handler handler, c_uint32_t ipv4, c_uint16_t port, void *data)
{

View File

@ -13,6 +13,9 @@ extern "C" {
CORE_DECLARE(status_t) gtp_server(sock_node_t *snode, sock_handler handler);
CORE_DECLARE(status_t) gtp_client(gtp_node_t *gnode);
CORE_DECLARE(status_t) gtp_server_list(list_t *list, sock_handler handler);
CORE_DECLARE(c_sockaddr_t *) gtp_local_addr_first(list_t *list);
CORE_DECLARE(status_t) gtp_listen(sock_id *sock,
sock_handler handler, c_uint32_t addr, c_uint16_t port, void *data);
CORE_DECLARE(status_t) gtp_close(sock_id sock);

View File

@ -336,7 +336,6 @@ status_t mme_context_parse_config()
{
int family = AF_UNSPEC;
int i, num = 0;
#define MAX_NUM_OF_HOSTNAME 16
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpc_port;
c_sockaddr_t *list = NULL;
@ -885,7 +884,6 @@ status_t mme_context_parse_config()
c_sockaddr_t *list = NULL;
int family = AF_UNSPEC;
int i, num = 0;
#define MAX_NUM_OF_HOSTNAME 16
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpc_port;
@ -1003,7 +1001,6 @@ status_t mme_context_parse_config()
c_sockaddr_t *list = NULL;
int family = AF_UNSPEC;
int i, num = 0;
#define MAX_NUM_OF_HOSTNAME 16
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpc_port;

View File

@ -42,87 +42,46 @@ static int _gtpv2_c_recv_cb(sock_id sock, void *data)
return 0;
}
static c_sockaddr_t *gtp_addr_find_by_family(list_t *list, int family)
{
gtp_node_t *gnode = NULL;
d_assert(list, return NULL,);
for (gnode = list_first(list); gnode; gnode = list_next(gnode))
{
c_sockaddr_t *addr = gnode->sa_list;
while(addr)
{
if (addr->c_sa_family == family)
{
return addr;
}
addr = addr->next;
}
}
return NULL;
}
status_t mme_gtp_open()
{
status_t rv;
sock_node_t *snode;
gtp_node_t *gnode;
for (snode = list_first(&mme_self()->gtpc_list);
snode; snode = list_next(snode))
{
rv = gtp_server(snode, _gtpv2_c_recv_cb);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
}
rv = gtp_server_list(&mme_self()->gtpc_list, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = gtp_server_list(&mme_self()->gtpc_list6, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
for (snode = list_first(&mme_self()->gtpc_list);
snode; snode = list_next(snode))
{
mme_self()->gtpc_addr = sock_local_addr(snode->sock);
if (mme_self()->gtpc_addr)
{
break;
}
}
for (snode = list_first(&mme_self()->gtpc_list6);
snode; snode = list_next(snode))
{
rv = gtp_server(snode, _gtpv2_c_recv_cb);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
}
for (snode = list_first(&mme_self()->gtpc_list6);
snode; snode = list_next(snode))
{
mme_self()->gtpc_addr6 = sock_local_addr(snode->sock);
if (mme_self()->gtpc_addr6)
{
break;
}
}
mme_self()->gtpc_addr = gtp_local_addr_first(&mme_self()->gtpc_list);
mme_self()->gtpc_addr6 = gtp_local_addr_first(&mme_self()->gtpc_list6);
d_assert(mme_self()->gtpc_addr || mme_self()->gtpc_addr6,
return CORE_ERROR, "No GTP Server");
for (gnode = list_first(&mme_self()->pgw_list);
gnode; gnode = list_next(gnode))
{
c_sockaddr_t *addr = gnode->sa_list;
while(addr)
{
if (addr->c_sa_family == AF_INET)
{
mme_self()->pgw_addr = addr;
break;
}
addr = addr->next;
}
}
for (gnode = list_first(&mme_self()->pgw_list);
gnode; gnode = list_next(gnode))
{
c_sockaddr_t *addr = gnode->sa_list;
while(addr)
{
if (addr->c_sa_family == AF_INET6)
{
mme_self()->pgw_addr6 = addr;
break;
}
addr = addr->next;
}
}
mme_self()->pgw_addr = gtp_addr_find_by_family(
&mme_self()->pgw_list, AF_INET);
mme_self()->pgw_addr6 = gtp_addr_find_by_family(
&mme_self()->pgw_list, AF_INET6);
d_assert(mme_self()->pgw_addr || mme_self()->pgw_addr6,
return CORE_ERROR,);
@ -131,19 +90,8 @@ status_t mme_gtp_open()
status_t mme_gtp_close()
{
sock_node_t *snode;
for (snode = list_first(&mme_self()->gtpc_list);
snode; snode = list_next(snode))
{
sock_delete(snode->sock);
}
for (snode = list_first(&mme_self()->gtpc_list6);
snode; snode = list_next(snode))
{
sock_delete(snode->sock);
}
sock_delete_list(&mme_self()->gtpc_list);
sock_delete_list(&mme_self()->gtpc_list6);
return CORE_OK;
}

View File

@ -70,9 +70,10 @@ status_t mme_s11_build_create_session_request(
mme_s11_teid.interface_type = GTP_F_TEID_S11_MME_GTP_C;
mme_s11_teid.teid = htonl(mme_ue->mme_s11_teid);
rv = gtp_sockaddr_to_f_teid(
mme_self()->gtpc_addr, mme_self()->gtpc_addr6,
&mme_s11_teid, &len);
mme_self()->gtpc_addr, mme_self()->gtpc_addr6, &mme_s11_teid);
d_assert(rv == CORE_OK, return CORE_ERROR,);
len = gtp_f_teid_len(&mme_s11_teid);
d_assert(len > 0, return CORE_ERROR,);
req->sender_f_teid_for_control_plane.presence = 1;
req->sender_f_teid_for_control_plane.data = &mme_s11_teid;
req->sender_f_teid_for_control_plane.len = len;
@ -93,8 +94,10 @@ status_t mme_s11_build_create_session_request(
else
{
rv = gtp_sockaddr_to_f_teid(
mme_self()->pgw_addr, mme_self()->pgw_addr6, &pgw_s5c_teid, &len);
mme_self()->pgw_addr, mme_self()->pgw_addr6, &pgw_s5c_teid);
d_assert(rv == CORE_OK, return CORE_ERROR,);
len = gtp_f_teid_len(&pgw_s5c_teid);
d_assert(len > 0, return CORE_ERROR,);
req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 1;
req->pgw_s5_s8_address_for_control_plane_or_pmip.data = &pgw_s5c_teid;
req->pgw_s5_s8_address_for_control_plane_or_pmip.len = len;

View File

@ -38,6 +38,8 @@ status_t pgw_context_init()
list_init(&self.gtpc_list);
list_init(&self.gtpc_list6);
list_init(&self.gtpu_list);
list_init(&self.gtpu_list6);
gtp_node_init();
list_init(&self.sgw_s5c_list);
@ -96,6 +98,8 @@ status_t pgw_context_final()
sock_remove_all_nodes(&self.gtpc_list);
sock_remove_all_nodes(&self.gtpc_list6);
sock_remove_all_nodes(&self.gtpu_list);
sock_remove_all_nodes(&self.gtpu_list6);
context_initiaized = 0;
@ -130,7 +134,8 @@ static status_t pgw_context_validation()
context_self()->config.path);
return CORE_ERROR;
}
if (self.gtpu_addr == 0)
if (list_first(&self.gtpu_list) == NULL &&
list_first(&self.gtpu_list6) == NULL)
{
d_error("No pgw.gtpu in '%s'",
context_self()->config.path);
@ -190,7 +195,6 @@ status_t pgw_context_parse_config()
{
int family = AF_UNSPEC;
int i, num = 0;
#define MAX_NUM_OF_HOSTNAME 16
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpc_port;
c_sockaddr_t *list = NULL;
@ -317,12 +321,12 @@ status_t pgw_context_parse_config()
yaml_iter_recurse(&pgw_iter, &gtpu_array);
do
{
#if 0
pgw_gtpu_t *gtpu = NULL;
#endif
int family = AF_UNSPEC;
const char *hostname = NULL;
c_uint16_t port = GTPV1_U_UDP_PORT;
int i, num = 0;
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpu_port;
c_sockaddr_t *list = NULL;
sock_node_t *node = NULL;
if (yaml_iter_type(&gtpu_array) == YAML_MAPPING_NODE)
{
@ -337,7 +341,7 @@ status_t pgw_context_parse_config()
yaml_iter_recurse(&gtpu_array, &gtpu_iter);
}
else if (yaml_iter_type(&gtpu_array) ==
YAML_SCALAR_NODE)
YAML_SCALAR_NODE)
{
break;
}
@ -366,11 +370,27 @@ status_t pgw_context_parse_config()
else if (!strcmp(gtpu_key, "addr") ||
!strcmp(gtpu_key, "name"))
{
hostname = yaml_iter_value(&gtpu_iter);
#if 1
if (hostname)
self.gtpu_addr = inet_addr(hostname);
#endif
yaml_iter_t hostname_iter;
yaml_iter_recurse(&gtpu_iter, &hostname_iter);
d_assert(yaml_iter_type(&hostname_iter) !=
YAML_MAPPING_NODE, return CORE_ERROR,);
do
{
if (yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE)
{
if (!yaml_iter_next(&hostname_iter))
break;
}
d_assert(num <= MAX_NUM_OF_HOSTNAME,
return CORE_ERROR,);
hostname[num++] =
yaml_iter_value(&hostname_iter);
} while(
yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE);
}
else if (!strcmp(gtpu_key, "port"))
{
@ -385,12 +405,43 @@ status_t pgw_context_parse_config()
d_warn("unknown key `%s`", gtpu_key);
}
#if 0
gtpu = pgw_gtpu_add(family, hostname, port);
d_assert(gtpu, return CORE_ERROR,);
#endif
list = NULL;
for (i = 0; i < num; i++)
{
rv = core_addaddrinfo(&list,
family, hostname[i], port, AI_PASSIVE);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
if (context_self()->parameter.no_ipv4 == 0)
{
rv = sock_add_node(&self.gtpu_list,
&node, list, AF_INET);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
if (context_self()->parameter.no_ipv6 == 0)
{
rv = sock_add_node(&self.gtpu_list6,
&node, list, AF_INET6);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
core_freeaddrinfo(list);
} while(yaml_iter_type(&gtpu_array) == YAML_SEQUENCE_NODE);
if (list_first(&self.gtpu_list) == NULL &&
list_first(&self.gtpu_list6) == NULL)
{
rv = sock_probe_node(
context_self()->parameter.no_ipv4 ?
NULL : &self.gtpu_list,
context_self()->parameter.no_ipv6 ?
NULL : &self.gtpu_list6,
self.gtpu_port);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
}
else if (!strcmp(pgw_key, "ue_network"))
{
@ -852,7 +903,6 @@ pgw_bearer_t* pgw_bearer_add(pgw_sess_t *sess)
list_init(&bearer->pf_list);
bearer->pgw_s5u_teid = bearer->index;
bearer->pgw_s5u_addr = pgw_self()->gtpu_addr;
bearer->sess = sess;
list_append(&sess->bearer_list, bearer);

View File

@ -21,18 +21,20 @@ extern "C" {
typedef struct _gtp_node_t gtp_node_t;
typedef struct _pgw_context_t {
c_uint32_t pgw_addr; /* PGW local address */
c_uint32_t pgw_addr; /* PGW local address */
c_uint32_t gtpc_port; /* PGW GTP-C local port */
c_uint32_t gtpu_port; /* PGW GTP-U local port */
list_t gtpc_list; /* PGW GTPC IPv4 Server List */
c_sockaddr_t *gtpc_addr; /* PGW GTPC IPv4 Address */
list_t gtpc_list6; /* PGW GTPC IPv6 Server List */
c_sockaddr_t *gtpc_addr6; /* PGW GTPC IPv6 Address */
c_uint32_t gtpu_addr; /* PGW GTP-U local address */
c_uint32_t gtpu_port; /* PGW GTP-U local port */
sock_id gtpu_sock; /* PGW GTP-U local listen socket */
list_t gtpu_list; /* PGW GTPU IPv4 Server List */
c_sockaddr_t *gtpu_addr; /* PGW GTPU IPv4 Address */
list_t gtpu_list6; /* PGW GTPU IPv6 Server List */
c_sockaddr_t *gtpu_addr6; /* PGW GTPU IPv6 Address */
const char* fd_conf_path; /* PGW freeDiameter conf path */
@ -103,13 +105,8 @@ typedef struct _pgw_bearer_t {
c_uint8_t ebi;
/* IMPORTANT!
* PGW-S5U-TEID is same with an index */
c_uint32_t pgw_s5u_teid;
c_uint32_t pgw_s5u_addr;
c_uint32_t sgw_s5u_teid;
c_uint32_t sgw_s5u_addr;
c_uint32_t pgw_s5u_teid; /* PGW_S5U is derived from INDEX */
c_uint32_t sgw_s5u_teid; /* SGW_S5U is received from SGW */
/* QoS Infomration */
qos_t qos;

View File

@ -150,62 +150,30 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data)
status_t pgw_gtp_open()
{
status_t rv;
sock_node_t *snode;
int i;
int rc;
for (snode = list_first(&pgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
rv = gtp_server(snode, _gtpv2_c_recv_cb);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
}
rv = gtp_server_list(&pgw_self()->gtpc_list, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = gtp_server_list(&pgw_self()->gtpc_list6, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
for (snode = list_first(&pgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
pgw_self()->gtpc_addr = sock_local_addr(snode->sock);
if (pgw_self()->gtpc_addr)
{
break;
}
}
for (snode = list_first(&pgw_self()->gtpc_list6);
snode; snode = list_next(snode))
{
rv = gtp_server(snode, _gtpv2_c_recv_cb);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
}
for (snode = list_first(&pgw_self()->gtpc_list6);
snode; snode = list_next(snode))
{
pgw_self()->gtpc_addr6 = sock_local_addr(snode->sock);
if (pgw_self()->gtpc_addr6)
{
break;
}
}
pgw_self()->gtpc_addr = gtp_local_addr_first(&pgw_self()->gtpc_list);
pgw_self()->gtpc_addr6 = gtp_local_addr_first(&pgw_self()->gtpc_list6);
d_assert(pgw_self()->gtpc_addr || pgw_self()->gtpc_addr6,
return CORE_ERROR, "No GTP Server");
rv = gtp_listen(&pgw_self()->gtpu_sock, _gtpv1_u_recv_cb,
pgw_self()->gtpu_addr, pgw_self()->gtpu_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-U Path for PGW");
return rv;
}
rv = gtp_server_list(&pgw_self()->gtpu_list, _gtpv1_u_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = gtp_server_list(&pgw_self()->gtpu_list6, _gtpv1_u_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
pgw_self()->gtpu_addr = gtp_local_addr_first(&pgw_self()->gtpu_list);
pgw_self()->gtpu_addr6 = gtp_local_addr_first(&pgw_self()->gtpu_list6);
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++)
{
@ -276,21 +244,13 @@ status_t pgw_gtp_open()
status_t pgw_gtp_close()
{
int i;
sock_node_t *snode;
for (snode = list_first(&pgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
sock_delete(snode->sock);
}
sock_delete_list(&pgw_self()->gtpc_list);
sock_delete_list(&pgw_self()->gtpc_list6);
for (snode = list_first(&pgw_self()->gtpc_list6);
snode; snode = list_next(snode))
{
sock_delete(snode->sock);
}
sock_delete_list(&pgw_self()->gtpu_list);
sock_delete_list(&pgw_self()->gtpu_list6);
sock_delete(pgw_self()->gtpu_sock);
for (i = 0; i < pgw_self()->num_of_ue_network; i++)
{
sock_delete(pgw_self()->ue_network[i].tun_link);

View File

@ -49,8 +49,10 @@ status_t pgw_s5c_build_create_session_response(
pgw_s5c_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_C;
pgw_s5c_teid.teid = htonl(sess->pgw_s5c_teid);
rv = gtp_sockaddr_to_f_teid(
pgw_self()->gtpc_addr, pgw_self()->gtpc_addr6, &pgw_s5c_teid, &len);
d_assert(rv == CORE_OK, return CORE_ERROR, );
pgw_self()->gtpc_addr, pgw_self()->gtpc_addr6, &pgw_s5c_teid);
d_assert(rv == CORE_OK, return CORE_ERROR,);
len = gtp_f_teid_len(&pgw_s5c_teid);
d_assert(len > 0, return CORE_ERROR,);
rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.
presence = 1;
rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.
@ -94,13 +96,16 @@ status_t pgw_s5c_build_create_session_response(
/* Data Plane(UL) : PGW-S5U */
memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
pgw_s5u_teid.ipv4 = 1;
pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid.ip.addr = bearer->pgw_s5u_addr;
pgw_s5u_teid.teid = htonl(bearer->pgw_s5u_teid);
rv = gtp_sockaddr_to_f_teid(
pgw_self()->gtpu_addr, pgw_self()->gtpu_addr6, &pgw_s5u_teid);
d_assert(rv == CORE_OK, return CORE_ERROR,);
len = gtp_f_teid_len(&pgw_s5u_teid);
d_assert(len > 0, return CORE_ERROR,);
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 1;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data = &pgw_s5u_teid;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.len = GTP_F_TEID_IPV4_LEN;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.len = len;
gtp_message.h.type = type;
rv = gtp_build_msg(pkbuf, &gtp_message);
@ -198,13 +203,16 @@ status_t pgw_s5c_build_create_bearer_request(
/* Data Plane(UL) : PGW_S5U */
memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
pgw_s5u_teid.ipv4 = 1;
pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid.ip.addr = bearer->pgw_s5u_addr;
pgw_s5u_teid.teid = htonl(bearer->pgw_s5u_teid);
rv = gtp_sockaddr_to_f_teid(
pgw_self()->gtpu_addr, pgw_self()->gtpu_addr6, &pgw_s5u_teid);
d_assert(rv == CORE_OK, return CORE_ERROR,);
len = gtp_f_teid_len(&pgw_s5u_teid);
d_assert(len > 0, return CORE_ERROR,);
req->bearer_contexts.s5_s8_u_sgw_f_teid.presence = 1;
req->bearer_contexts.s5_s8_u_sgw_f_teid.data = &pgw_s5u_teid;
req->bearer_contexts.s5_s8_u_sgw_f_teid.len = GTP_F_TEID_IPV4_LEN;
req->bearer_contexts.s5_s8_u_sgw_f_teid.len = len;
/* Bearer QoS */
memset(&bearer_qos, 0, sizeof(bearer_qos));

View File

@ -76,7 +76,6 @@ void pgw_s5c_handle_create_session_request(
sgw_s5u_teid = req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.data;
d_assert(sgw_s5u_teid, return, "Null param");
bearer->sgw_s5u_teid = ntohl(sgw_s5u_teid->teid);
bearer->sgw_s5u_addr = sgw_s5u_teid->ip.addr;
sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid);
if (!sgw)
{
@ -176,7 +175,6 @@ void pgw_s5c_handle_create_bearer_response(
/* Data Plane(DL) : SGW-S5U */
sgw_s5u_teid = req->bearer_contexts.s5_s8_u_sgw_f_teid.data;
bearer->sgw_s5u_teid = ntohl(sgw_s5u_teid->teid);
bearer->sgw_s5u_addr = sgw_s5u_teid->ip.addr;
sgw = gtp_find_node(&pgw_self()->sgw_s5u_list, sgw_s5u_teid);
if (!sgw)
{

View File

@ -37,6 +37,8 @@ status_t sgw_context_init()
list_init(&self.gtpc_list);
list_init(&self.gtpc_list6);
list_init(&self.gtpu_list);
list_init(&self.gtpu_list6);
gtp_node_init();
list_init(&self.mme_s11_list);
@ -79,6 +81,8 @@ status_t sgw_context_final()
sock_remove_all_nodes(&self.gtpc_list);
sock_remove_all_nodes(&self.gtpc_list6);
sock_remove_all_nodes(&self.gtpu_list);
sock_remove_all_nodes(&self.gtpu_list6);
context_initialized = 0;
@ -107,7 +111,8 @@ static status_t sgw_context_validation()
context_self()->config.path);
return CORE_ERROR;
}
if (self.gtpu_addr == 0)
if (list_first(&self.gtpu_list) == NULL &&
list_first(&self.gtpu_list6) == NULL)
{
d_error("No sgw.gtpu in '%s'",
context_self()->config.path);
@ -151,7 +156,6 @@ status_t sgw_context_parse_config()
{
int family = AF_UNSPEC;
int i, num = 0;
#define MAX_NUM_OF_HOSTNAME 16
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpc_port;
c_sockaddr_t *list = NULL;
@ -278,12 +282,12 @@ status_t sgw_context_parse_config()
yaml_iter_recurse(&sgw_iter, &gtpu_array);
do
{
#if 0
sgw_gtpu_t *gtpu = NULL;
#endif
int family = AF_UNSPEC;
const char *hostname = NULL;
c_uint16_t port = GTPV1_U_UDP_PORT;
int i, num = 0;
const char *hostname[MAX_NUM_OF_HOSTNAME];
c_uint16_t port = self.gtpu_port;
c_sockaddr_t *list = NULL;
sock_node_t *node = NULL;
if (yaml_iter_type(&gtpu_array) == YAML_MAPPING_NODE)
{
@ -298,7 +302,7 @@ status_t sgw_context_parse_config()
yaml_iter_recurse(&gtpu_array, &gtpu_iter);
}
else if (yaml_iter_type(&gtpu_array) ==
YAML_SCALAR_NODE)
YAML_SCALAR_NODE)
{
break;
}
@ -327,11 +331,27 @@ status_t sgw_context_parse_config()
else if (!strcmp(gtpu_key, "addr") ||
!strcmp(gtpu_key, "name"))
{
hostname = yaml_iter_value(&gtpu_iter);
#if 1
if (hostname)
self.gtpu_addr = inet_addr(hostname);
#endif
yaml_iter_t hostname_iter;
yaml_iter_recurse(&gtpu_iter, &hostname_iter);
d_assert(yaml_iter_type(&hostname_iter) !=
YAML_MAPPING_NODE, return CORE_ERROR,);
do
{
if (yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE)
{
if (!yaml_iter_next(&hostname_iter))
break;
}
d_assert(num <= MAX_NUM_OF_HOSTNAME,
return CORE_ERROR,);
hostname[num++] =
yaml_iter_value(&hostname_iter);
} while(
yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE);
}
else if (!strcmp(gtpu_key, "port"))
{
@ -346,12 +366,43 @@ status_t sgw_context_parse_config()
d_warn("unknown key `%s`", gtpu_key);
}
#if 0
gtpu = sgw_gtpu_add(family, hostname, port);
d_assert(gtpu, return CORE_ERROR,);
#endif
list = NULL;
for (i = 0; i < num; i++)
{
rv = core_addaddrinfo(&list,
family, hostname[i], port, AI_PASSIVE);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
if (context_self()->parameter.no_ipv4 == 0)
{
rv = sock_add_node(&self.gtpu_list,
&node, list, AF_INET);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
if (context_self()->parameter.no_ipv6 == 0)
{
rv = sock_add_node(&self.gtpu_list6,
&node, list, AF_INET6);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
core_freeaddrinfo(list);
} while(yaml_iter_type(&gtpu_array) == YAML_SEQUENCE_NODE);
if (list_first(&self.gtpu_list) == NULL &&
list_first(&self.gtpu_list6) == NULL)
{
rv = sock_probe_node(
context_self()->parameter.no_ipv4 ?
NULL : &self.gtpu_list,
context_self()->parameter.no_ipv6 ?
NULL : &self.gtpu_list6,
self.gtpu_port);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
}
else
d_warn("unknown key `%s`", sgw_key);
@ -813,7 +864,6 @@ sgw_tunnel_t* sgw_tunnel_add(sgw_bearer_t *bearer, c_uint8_t interface_type)
tunnel->interface_type = interface_type;
tunnel->local_teid = tunnel->index;
tunnel->local_addr = sgw_self()->gtpu_addr;
tunnel->bearer = bearer;

View File

@ -21,15 +21,17 @@ typedef struct _gtp_node_t gtp_node_t;
typedef struct _sgw_context_t {
c_uint32_t gtpc_port; /* Default GTPC port */
c_uint32_t gtpu_port; /* Default GTPU port */
list_t gtpc_list; /* SGW GTPC IPv4 Server List */
c_sockaddr_t *gtpc_addr; /* SGW GTPC IPv4 Address */
list_t gtpc_list6; /* SGW GTPC IPv6 Server List */
c_sockaddr_t *gtpc_addr6; /* SGW GTPC IPv6 Address */
c_uint32_t gtpu_addr; /* GTP-U local address */
c_uint32_t gtpu_port; /* GTP-U local port */
sock_id gtpu_sock; /* GTP-U local listen socket */
list_t gtpu_list; /* SGW GTPU IPv4 Server List */
c_sockaddr_t *gtpu_addr; /* SGW GTPU IPv4 Address */
list_t gtpu_list6; /* SGW GTPU IPv6 Server List */
c_sockaddr_t *gtpu_addr6; /* SGW GTPU IPv6 Address */
msgq_id queue_id; /* Queue for processing SGW control plane */
tm_service_t tm_service;/* Timer Service */
@ -119,9 +121,7 @@ typedef struct _sgw_tunnel_t {
c_uint8_t interface_type;
c_uint32_t local_teid;
c_uint32_t local_addr;
c_uint32_t remote_teid;
c_uint32_t remote_addr;
/* Related Context */
sgw_bearer_t *bearer;

View File

@ -220,88 +220,39 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data)
status_t sgw_gtp_open()
{
status_t rv;
sock_node_t *snode;
for (snode = list_first(&sgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
rv = gtp_server(snode, _gtpv2_c_recv_cb);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
}
rv = gtp_server_list(&sgw_self()->gtpc_list, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = gtp_server_list(&sgw_self()->gtpc_list6, _gtpv2_c_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
for (snode = list_first(&sgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
sgw_self()->gtpc_addr = sock_local_addr(snode->sock);
if (sgw_self()->gtpc_addr)
{
break;
}
}
for (snode = list_first(&sgw_self()->gtpc_list6);
snode; snode = list_next(snode))
{
rv = gtp_server(snode, _gtpv2_c_recv_cb);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-C Path for SGW");
return rv;
}
}
for (snode = list_first(&sgw_self()->gtpc_list6);
snode; snode = list_next(snode))
{
sgw_self()->gtpc_addr6 = sock_local_addr(snode->sock);
if (sgw_self()->gtpc_addr6)
{
break;
}
}
sgw_self()->gtpc_addr = gtp_local_addr_first(&sgw_self()->gtpc_list);
sgw_self()->gtpc_addr6 = gtp_local_addr_first(&sgw_self()->gtpc_list6);
d_assert(sgw_self()->gtpc_addr || sgw_self()->gtpc_addr6,
return CORE_ERROR, "No GTP Server");
rv = gtp_listen(&sgw_self()->gtpu_sock, _gtpv1_u_recv_cb,
sgw_self()->gtpu_addr, sgw_self()->gtpu_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish GTP-U Path for eNB/SGW");
return rv;
}
rv = gtp_server_list(&sgw_self()->gtpu_list, _gtpv1_u_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = gtp_server_list(&sgw_self()->gtpu_list6, _gtpv1_u_recv_cb);
d_assert(rv == CORE_OK, return CORE_ERROR,);
sgw_self()->gtpu_addr = gtp_local_addr_first(&sgw_self()->gtpu_list);
sgw_self()->gtpu_addr6 = gtp_local_addr_first(&sgw_self()->gtpu_list6);
d_assert(sgw_self()->gtpu_addr || sgw_self()->gtpu_addr6,
return CORE_ERROR, "No GTP Server");
return CORE_OK;
}
status_t sgw_gtp_close()
{
status_t rv;
sock_delete_list(&sgw_self()->gtpc_list);
sock_delete_list(&sgw_self()->gtpc_list6);
sock_node_t *snode;
for (snode = list_first(&sgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
sock_delete(snode->sock);
}
for (snode = list_first(&sgw_self()->gtpc_list6);
snode; snode = list_next(snode))
{
sock_delete(snode->sock);
}
rv = gtp_close(sgw_self()->gtpu_sock);
if (rv != CORE_OK)
{
d_error("Can't close GTP-U Path for eNB/PGW");
return rv;
}
sock_delete_list(&sgw_self()->gtpu_list);
sock_delete_list(&sgw_self()->gtpu_list6);
return CORE_OK;
}
@ -311,7 +262,6 @@ status_t sgw_gtp_send_end_marker(sgw_bearer_t *bearer)
status_t rv;
pkbuf_t *pkbuf = NULL;
gtp_header_t *h = NULL;
gtp_node_t gnode;
sgw_tunnel_t *s1u_tunnel = NULL;
d_assert(bearer, return CORE_ERROR,);
@ -333,13 +283,7 @@ status_t sgw_gtp_send_end_marker(sgw_bearer_t *bearer)
h->type = GTPU_MSGTYPE_END_MARKER;
h->teid = htonl(s1u_tunnel->remote_teid);
memset(&gnode, 0, sizeof(gtp_node_t));
gnode.old_addr.sin.sin_addr.s_addr = s1u_tunnel->remote_addr;
gnode.old_addr.c_sa_port = htons(GTPV1_U_UDP_PORT);
gnode.old_addr.c_sa_family = AF_INET;
gnode.sock = sgw_self()->gtpu_sock;
rv = gtp_send(&gnode, pkbuf);
rv = gtp_send(s1u_tunnel->gnode, pkbuf);
d_assert(rv == CORE_OK, , "gtp send failed");
pkbuf_free(pkbuf);

View File

@ -100,8 +100,10 @@ void sgw_s11_handle_create_session_request(
sgw_s5c_teid.interface_type = GTP_F_TEID_S5_S8_SGW_GTP_C;
sgw_s5c_teid.teid = htonl(sess->sgw_s5c_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpc_addr, sgw_self()->gtpc_addr6, &sgw_s5c_teid, &len);
sgw_self()->gtpc_addr, sgw_self()->gtpc_addr6, &sgw_s5c_teid);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&sgw_s5c_teid);
d_assert(len > 0, return,);
req->sender_f_teid_for_control_plane.presence = 1;
req->sender_f_teid_for_control_plane.data = &sgw_s5c_teid;
req->sender_f_teid_for_control_plane.len = len;
@ -131,13 +133,15 @@ void sgw_s11_handle_create_session_request(
/* Data Plane(DL) : SGW-S5U */
memset(&sgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s5u_teid.teid = htonl(s5u_tunnel->local_teid);
sgw_s5u_teid.ipv4 = 1;
sgw_s5u_teid.ip.addr = s5u_tunnel->local_addr;
sgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_SGW_GTP_U;
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpu_addr, sgw_self()->gtpu_addr6, &sgw_s5u_teid);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&sgw_s5u_teid);
d_assert(len > 0, return,);
req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence = 1;
req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid;
req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.len =
GTP_F_TEID_IPV4_LEN;
req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.len = len;
/* Set User Location Information */
decoded = gtp_parse_uli(&uli, &req->user_location_information);
@ -228,7 +232,6 @@ CORE_DECLARE(void) sgw_s11_handle_modify_bearer_request(gtp_xact_t *s11_xact,
/* Data Plane(DL) : eNB-S1U */
enb_s1u_teid = req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data;
s1u_tunnel->remote_teid = ntohl(enb_s1u_teid->teid);
s1u_tunnel->remote_addr = enb_s1u_teid->ip.addr;
enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid);
if (!enb)
{
@ -332,6 +335,7 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
gtp_f_teid_t *sgw_s1u_teid = NULL, *enb_s1u_teid = NULL;
gtp_f_teid_t sgw_s5u_teid, pgw_s5u_teid;
int len;
gtp_uli_t uli;
d_assert(s11_xact, return, "Null param");
@ -390,7 +394,6 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
/* Data Plane(DL) : eNB-S1U */
enb_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data;
s1u_tunnel->remote_teid = ntohl(enb_s1u_teid->teid);
s1u_tunnel->remote_addr = enb_s1u_teid->ip.addr;
enb = gtp_find_node(&sgw_self()->enb_s1u_list, enb_s1u_teid);
if (!enb)
{
@ -422,22 +425,27 @@ void sgw_s11_handle_create_bearer_response(gtp_xact_t *s11_xact,
/* Data Plane(DL) : SGW-S5U */
memset(&sgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s5u_teid.teid = htonl(s5u_tunnel->local_teid);
sgw_s5u_teid.ipv4 = 1;
sgw_s5u_teid.ip.addr = s5u_tunnel->local_addr;
sgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_SGW_GTP_U;
sgw_s5u_teid.teid = htonl(s5u_tunnel->local_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpu_addr, sgw_self()->gtpu_addr6, &sgw_s5u_teid);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&sgw_s5u_teid);
d_assert(len > 0, return,);
req->bearer_contexts.s5_s8_u_sgw_f_teid.presence = 1;
req->bearer_contexts.s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid;
req->bearer_contexts.s5_s8_u_sgw_f_teid.len = GTP_F_TEID_IPV4_LEN;
req->bearer_contexts.s5_s8_u_sgw_f_teid.len = len;
/* Data Plane(DL) : PGW-S5U */
memset(&pgw_s5u_teid, 0, sizeof(gtp_f_teid_t));
pgw_s5u_teid.teid = htonl(s5u_tunnel->remote_teid);
pgw_s5u_teid.ip.addr = s5u_tunnel->remote_addr;
d_assert(s5u_tunnel->gnode, return,);
len = gtp_f_teid_len(&s5u_tunnel->gnode->f_teid);
d_assert(len > 0, return,);
d_assert(gtp_f_teid_copy(&pgw_s5u_teid, &s5u_tunnel->gnode->f_teid), return,);
pgw_s5u_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid.teid = htonl(s5u_tunnel->remote_teid);
req->bearer_contexts.s5_s8_u_pgw_f_teid.presence = 1;
req->bearer_contexts.s5_s8_u_pgw_f_teid.data = &pgw_s5u_teid;
req->bearer_contexts.s5_s8_u_pgw_f_teid.len = GTP_F_TEID_IPV4_LEN;
req->bearer_contexts.s5_s8_u_pgw_f_teid.len = len;
gtp_message->h.type = GTP_CREATE_BEARER_RESPONSE_TYPE;
gtp_message->h.teid = sess->pgw_s5c_teid;
@ -490,7 +498,6 @@ void sgw_s11_handle_release_access_bearers_request(gtp_xact_t *s11_xact,
d_assert(s1u_tunnel, return, "Null param");
s1u_tunnel->remote_teid = 0;
s1u_tunnel->remote_addr = 0;
bearer = next_bearer;
}
@ -595,6 +602,7 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
gtp_f_teid_t *req_teid = NULL;
gtp_f_teid_t rsp_dl_teid[GTP_MAX_NUM_OF_INDIRECT_TUNNEL];
gtp_f_teid_t rsp_ul_teid[GTP_MAX_NUM_OF_INDIRECT_TUNNEL];
int len;
d_assert(sgw_ue, return, "Null param");
d_assert(s11_xact, return, "Null param");
@ -635,8 +643,6 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
d_assert(tunnel, return, "No Tunnel Context");
tunnel->remote_teid = ntohl(req_teid->teid);
tunnel->remote_addr = req_teid->ip.addr;
enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid);
if (!enb)
{
@ -654,14 +660,16 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
SETUP_GTP_NODE(tunnel, enb);
memset(&rsp_dl_teid[i], 0, sizeof(gtp_f_teid_t));
rsp_dl_teid[i].ipv4 = 1;
rsp_dl_teid[i].ip.addr = tunnel->local_addr;
rsp_dl_teid[i].teid = htonl(tunnel->local_teid);
rsp_dl_teid[i].interface_type = tunnel->interface_type;
rsp_dl_teid[i].teid = htonl(tunnel->local_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpu_addr, sgw_self()->gtpu_addr6, &rsp_dl_teid[i]);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&rsp_dl_teid[i]);
d_assert(len > 0, return,);
rsp_bearers[i]->s4_u_sgsn_f_teid.presence = 1;
rsp_bearers[i]->s4_u_sgsn_f_teid.data = &rsp_dl_teid[i];
rsp_bearers[i]->s4_u_sgsn_f_teid.len = GTP_F_TEID_IPV4_LEN;
rsp_bearers[i]->s4_u_sgsn_f_teid.len = len;
}
if (req_bearers[i]->s12_rnc_f_teid.presence)
@ -674,7 +682,6 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
d_assert(tunnel, return, "No Tunnel Context");
tunnel->remote_teid = ntohl(req_teid->teid);
tunnel->remote_addr = req_teid->ip.addr;
enb = gtp_find_node(&sgw_self()->enb_s1u_list, req_teid);
if (!enb)
{
@ -692,14 +699,16 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
SETUP_GTP_NODE(tunnel, enb);
memset(&rsp_ul_teid[i], 0, sizeof(gtp_f_teid_t));
rsp_ul_teid[i].ipv4 = 1;
rsp_ul_teid[i].ip.addr = tunnel->local_addr;
rsp_ul_teid[i].teid = htonl(tunnel->local_teid);
rsp_ul_teid[i].interface_type = tunnel->interface_type;
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpu_addr, sgw_self()->gtpu_addr6, &rsp_ul_teid[i]);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&rsp_ul_teid[i]);
d_assert(len > 0, return,);
rsp_bearers[i]->s2b_u_epdg_f_teid_5.presence = 1;
rsp_bearers[i]->s2b_u_epdg_f_teid_5.data = &rsp_ul_teid[i];
rsp_bearers[i]->s2b_u_epdg_f_teid_5.len = GTP_F_TEID_IPV4_LEN;
rsp_bearers[i]->s2b_u_epdg_f_teid_5.len = len;
}
if (req_bearers[i]->s1_u_enodeb_f_teid.presence ||

View File

@ -84,7 +84,6 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data;
d_assert(pgw_s5u_teid, return, "Null param");
s5u_tunnel->remote_teid = ntohl(pgw_s5u_teid->teid);
s5u_tunnel->remote_addr = pgw_s5u_teid->ip.addr;
pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid);
if (!pgw)
{
@ -109,22 +108,26 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
sgw_s11_teid.interface_type = GTP_F_TEID_S11_S4_SGW_GTP_C;
sgw_s11_teid.teid = htonl(sgw_ue->sgw_s11_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpc_addr, sgw_self()->gtpc_addr6,
&sgw_s11_teid, &len);
d_assert(rv == CORE_OK, return, );
sgw_self()->gtpc_addr, sgw_self()->gtpc_addr6, &sgw_s11_teid);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&sgw_s11_teid);
d_assert(len > 0, return,);
rsp->sender_f_teid_for_control_plane.presence = 1;
rsp->sender_f_teid_for_control_plane.data = &sgw_s11_teid;
rsp->sender_f_teid_for_control_plane.len = len;
/* Send Data Plane(UL) : SGW-S1U */
memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s1u_teid.ipv4 = 1;
sgw_s1u_teid.interface_type = s1u_tunnel->interface_type;
sgw_s1u_teid.ip.addr = s1u_tunnel->local_addr;
sgw_s1u_teid.teid = htonl(s1u_tunnel->local_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpu_addr, sgw_self()->gtpu_addr6, &sgw_s1u_teid);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&sgw_s1u_teid);
d_assert(len > 0, return,);
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1;
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = &sgw_s1u_teid;
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN;
rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = len;
rv = gtp_xact_commit(s5c_xact);
d_assert(rv == CORE_OK, return, "xact_commit error");
@ -224,6 +227,7 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
gtp_f_teid_t *pgw_s5u_teid = NULL;
gtp_f_teid_t sgw_s1u_teid;
int len;
d_assert(sess, return, "Null param");
sgw_ue = sess->sgw_ue;
@ -265,7 +269,6 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
pgw_s5u_teid = req->bearer_contexts.s5_s8_u_sgw_f_teid.data;
d_assert(pgw_s5u_teid, return, "Null param");
s5u_tunnel->remote_teid = ntohl(pgw_s5u_teid->teid);
s5u_tunnel->remote_addr = pgw_s5u_teid->ip.addr;
pgw = gtp_find_node(&sgw_self()->pgw_s5u_list, pgw_s5u_teid);
if (!pgw)
{
@ -287,13 +290,16 @@ void sgw_s5c_handle_create_bearer_request(gtp_xact_t *s5c_xact,
/* Send Data Plane(UL) : SGW-S1U */
memset(&sgw_s1u_teid, 0, sizeof(gtp_f_teid_t));
sgw_s1u_teid.ipv4 = 1;
sgw_s1u_teid.interface_type = s1u_tunnel->interface_type;
sgw_s1u_teid.ip.addr = s1u_tunnel->local_addr;
sgw_s1u_teid.teid = htonl(s1u_tunnel->local_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_self()->gtpu_addr, sgw_self()->gtpu_addr6, &sgw_s1u_teid);
d_assert(rv == CORE_OK, return,);
len = gtp_f_teid_len(&sgw_s1u_teid);
d_assert(len > 0, return,);
req->bearer_contexts.s1_u_enodeb_f_teid.presence = 1;
req->bearer_contexts.s1_u_enodeb_f_teid.data = &sgw_s1u_teid;
req->bearer_contexts.s1_u_enodeb_f_teid.len = GTP_F_TEID_IPV4_LEN;
req->bearer_contexts.s1_u_enodeb_f_teid.len = len;
gtp_message->h.type = GTP_CREATE_BEARER_REQUEST_TYPE;
gtp_message->h.teid = sgw_ue->mme_s11_teid;

View File

@ -15,6 +15,7 @@ static void handover_test1(abts_case *tc, void *data)
{
status_t rv;
sock_id sock1, sock2;
sock_id gtpu;
pkbuf_t *sendbuf;
pkbuf_t *recvbuf;
s1ap_message_t message;
@ -112,6 +113,10 @@ static void handover_test1(abts_case *tc, void *data)
rv = tests1ap_enb_connect(&sock2);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* eNB connects to SGW */
rv = testgtpu_enb_connect(&gtpu);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* S1-Setup Reqeust/Response for Source eNB */
rv = tests1ap_build_setup_req(
&sendbuf, S1ap_ENB_ID_PR_macroENB_ID, 0x54f64);
@ -271,12 +276,36 @@ static void handover_test1(abts_case *tc, void *data)
CORE_HEX(_nh1, strlen(_nh1), tmp), 33) == 0);
pkbuf_free(recvbuf);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Send Path Switch Request */
rv = tests1ap_build_path_switch_request(&sendbuf, 1);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = tests1ap_enb_send(sock1, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive Path Switch Ack */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = tests1ap_enb_read(sock1, recvbuf);
@ -301,6 +330,10 @@ static void handover_test1(abts_case *tc, void *data)
rv = tests1ap_enb_close(sock2);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* eNB disonncect from SGW */
rv = testgtpu_enb_close(gtpu);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
core_sleep(time_from_msec(300));
}
@ -308,6 +341,7 @@ static void handover_test2(abts_case *tc, void *data)
{
status_t rv;
sock_id sock1, sock2;
sock_id gtpu;
pkbuf_t *sendbuf;
pkbuf_t *recvbuf;
s1ap_message_t message;
@ -399,6 +433,10 @@ static void handover_test2(abts_case *tc, void *data)
rv = tests1ap_enb_connect(&sock2);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* eNB connects to SGW */
rv = testgtpu_enb_connect(&gtpu);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* S1-Setup Reqeust/Response for Source eNB */
rv = tests1ap_build_setup_req(
&sendbuf, S1ap_ENB_ID_PR_macroENB_ID, 0x001f2);
@ -598,6 +636,18 @@ static void handover_test2(abts_case *tc, void *data)
rv = tests1ap_enb_send(sock2, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive UE Context Release Command */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = tests1ap_enb_read(sock1, recvbuf);
@ -654,6 +704,18 @@ static void handover_test2(abts_case *tc, void *data)
rv = tests1ap_enb_send(sock1, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive End Mark */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = testgtpu_enb_read(gtpu, recvbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(recvbuf);
/* Receive UE Context Release Command */
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
rv = tests1ap_enb_read(sock2, recvbuf);
@ -734,6 +796,10 @@ static void handover_test2(abts_case *tc, void *data)
rv = tests1ap_enb_close(sock2);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
/* eNB disonncect from SGW */
rv = testgtpu_enb_close(gtpu);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
core_sleep(time_from_msec(300));
}