SGW/PGW GTP-U is added
This commit is contained in:
parent
f8f18eb6f5
commit
03a6bb7902
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, >pu_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(>pu_array) == YAML_MAPPING_NODE)
|
||||
{
|
||||
|
@ -337,7 +341,7 @@ status_t pgw_context_parse_config()
|
|||
yaml_iter_recurse(>pu_array, >pu_iter);
|
||||
}
|
||||
else if (yaml_iter_type(>pu_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(>pu_iter);
|
||||
#if 1
|
||||
if (hostname)
|
||||
self.gtpu_addr = inet_addr(hostname);
|
||||
#endif
|
||||
yaml_iter_t hostname_iter;
|
||||
yaml_iter_recurse(>pu_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(>pu_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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, >p_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));
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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, >pu_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(>pu_array) == YAML_MAPPING_NODE)
|
||||
{
|
||||
|
@ -298,7 +302,7 @@ status_t sgw_context_parse_config()
|
|||
yaml_iter_recurse(>pu_array, >pu_iter);
|
||||
}
|
||||
else if (yaml_iter_type(>pu_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(>pu_iter);
|
||||
#if 1
|
||||
if (hostname)
|
||||
self.gtpu_addr = inet_addr(hostname);
|
||||
#endif
|
||||
yaml_iter_t hostname_iter;
|
||||
yaml_iter_recurse(>pu_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(>pu_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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(>pu);
|
||||
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(>pu);
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue