SGW GTP-C server is added

This commit is contained in:
Sukchan Lee 2017-12-05 21:11:36 +09:00
parent 1ab90bcef4
commit a747f91b39
8 changed files with 229 additions and 59 deletions

View File

@ -13,6 +13,7 @@
#include "s1ap_message.h"
#include "gtp_xact.h"
#include "gtp_node.h"
#include "gtp_path.h"
#include "fd_lib.h"
#include "context.h"
@ -972,6 +973,9 @@ status_t mme_context_parse_config()
context_self()->parameter.prefer_ipv4);
d_assert(rv == CORE_OK, return CORE_ERROR,);
rv = gtp_client(sgw);
d_assert(rv == CORE_OK, return CORE_ERROR,);
core_freeaddrinfo(list);
} while(yaml_iter_type(&gtpc_array) == YAML_SEQUENCE_NODE);

View File

@ -42,10 +42,11 @@ static int _gtpv2_c_recv_cb(sock_id sock, void *data)
return 0;
}
static status_t mme_gtp_server()
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))
@ -92,25 +93,6 @@ static status_t mme_gtp_server()
d_assert(mme_self()->gtpc_addr || mme_self()->gtpc_addr6,
return CORE_ERROR, "No GTP Server");
return CORE_OK;
}
static status_t mme_gtp_client()
{
status_t rv;
gtp_node_t *gnode = NULL;
for (gnode = list_first(&mme_self()->sgw_list);
gnode; gnode = list_next(gnode))
{
rv = gtp_client(gnode);
if (rv != CORE_OK)
{
d_error("Can't connect GTP-C Path to SGW");
return rv;
}
}
mme_self()->sgw = list_first(&mme_self()->sgw_list);
d_assert(mme_self()->sgw, return CORE_ERROR,);
@ -150,19 +132,6 @@ static status_t mme_gtp_client()
return CORE_OK;
}
status_t mme_gtp_open()
{
status_t rv;
rv = mme_gtp_server();
if (rv != CORE_OK) return CORE_ERROR;
rv = mme_gtp_client();
if (rv != CORE_OK) return CORE_ERROR;
return CORE_OK;
}
status_t mme_gtp_close()
{
sock_node_t *snode;

View File

@ -71,6 +71,7 @@ status_t mme_s11_build_create_session_request(
mme_s11_teid.teid = htonl(mme_ue->mme_s11_teid);
rv = gtp_sockaddr_to_f_teid(
mme_ue->mme_s11_ipv4, mme_ue->mme_s11_ipv6, &mme_s11_teid, &len);
d_assert(rv == CORE_OK, 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;
@ -92,6 +93,7 @@ status_t mme_s11_build_create_session_request(
{
rv = gtp_sockaddr_to_f_teid(
mme_self()->pgw_addr, mme_self()->pgw_addr6, &pgw_s5c_teid, &len);
d_assert(rv == CORE_OK, 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

@ -35,6 +35,9 @@ status_t sgw_context_init()
memset(&self, 0, sizeof(sgw_context_t));
list_init(&self.gtpc_list);
list_init(&self.gtpc_list6);
gtp_node_init();
list_init(&self.mme_list);
list_init(&self.pgw_list);
@ -70,6 +73,9 @@ status_t sgw_context_final()
gtp_remove_all_nodes(&self.pgw_list);
gtp_node_final();
sock_remove_all_nodes(&self.gtpc_list);
sock_remove_all_nodes(&self.gtpc_list6);
context_initialized = 0;
return CORE_OK;
@ -90,9 +96,10 @@ static status_t sgw_context_prepare()
static status_t sgw_context_validation()
{
if (self.gtpc_addr == 0)
if (list_first(&self.gtpc_list) == NULL &&
list_first(&self.gtpc_list6) == NULL)
{
d_error("No sgw.gtpc in '%s'",
d_error("No mme.gtpc in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
@ -132,6 +139,7 @@ status_t sgw_context_parse_config()
{
const char *sgw_key = yaml_iter_key(&sgw_iter);
d_assert(sgw_key, return CORE_ERROR,);
#if 0
if (!strcmp(sgw_key, "gtpc"))
{
yaml_iter_t gtpc_array, gtpc_iter;
@ -189,7 +197,7 @@ status_t sgw_context_parse_config()
hostname = yaml_iter_value(&gtpc_iter);
#if 1
if (hostname)
self.gtpc_addr = inet_addr(hostname);
self.old_gtpc_addr = inet_addr(hostname);
#endif
}
else if (!strcmp(gtpc_key, "port"))
@ -212,6 +220,136 @@ status_t sgw_context_parse_config()
} while(yaml_iter_type(&gtpc_array) == YAML_SEQUENCE_NODE);
}
#else
if (!strcmp(sgw_key, "gtpc"))
{
yaml_iter_t gtpc_array, gtpc_iter;
yaml_iter_recurse(&sgw_iter, &gtpc_array);
do
{
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;
sock_node_t *node = NULL;
if (yaml_iter_type(&gtpc_array) == YAML_MAPPING_NODE)
{
memcpy(&gtpc_iter, &gtpc_array,
sizeof(yaml_iter_t));
}
else if (yaml_iter_type(&gtpc_array) ==
YAML_SEQUENCE_NODE)
{
if (!yaml_iter_next(&gtpc_array))
break;
yaml_iter_recurse(&gtpc_array, &gtpc_iter);
}
else if (yaml_iter_type(&gtpc_array) ==
YAML_SCALAR_NODE)
{
break;
}
else
d_assert(0, return CORE_ERROR,);
while(yaml_iter_next(&gtpc_iter))
{
const char *gtpc_key =
yaml_iter_key(&gtpc_iter);
d_assert(gtpc_key,
return CORE_ERROR,);
if (!strcmp(gtpc_key, "family"))
{
const char *v = yaml_iter_value(&gtpc_iter);
if (v) family = atoi(v);
if (family != AF_UNSPEC &&
family != AF_INET && family != AF_INET6)
{
d_warn("Ignore family(%d) : AF_UNSPEC(0), "
"AF_INET(2), AF_INET6(30) ", family);
family = AF_UNSPEC;
}
}
else if (!strcmp(gtpc_key, "addr") ||
!strcmp(gtpc_key, "name"))
{
yaml_iter_t hostname_iter;
yaml_iter_recurse(&gtpc_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(gtpc_key, "port"))
{
const char *v = yaml_iter_value(&gtpc_iter);
if (v)
{
port = atoi(v);
self.gtpc_port = port;
}
}
else
d_warn("unknown key `%s`", gtpc_key);
}
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.gtpc_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.gtpc_list,
&node, list, AF_INET6);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
core_freeaddrinfo(list);
} while(yaml_iter_type(&gtpc_array) == YAML_SEQUENCE_NODE);
if (list_first(&self.gtpc_list) == NULL &&
list_first(&self.gtpc_list6) == NULL)
{
rv = sock_probe_node(
context_self()->parameter.no_ipv4 ?
NULL : &self.gtpc_list,
context_self()->parameter.no_ipv6 ?
NULL : &self.gtpc_list6,
self.gtpc_port);
d_assert(rv == CORE_OK, return CORE_ERROR,);
}
}
#endif
else if (!strcmp(sgw_key, "gtpu"))
{
yaml_iter_t gtpu_array, gtpu_iter;
@ -360,7 +498,8 @@ sgw_ue_t* sgw_ue_add(
d_assert(sgw_ue, return NULL, "Null param");
sgw_ue->sgw_s11_teid = sgw_ue->index;
sgw_ue->sgw_s11_addr = sgw_self()->gtpc_addr;
sgw_ue->sgw_s11_ipv4 = sgw_self()->gtpc_addr;
sgw_ue->sgw_s11_ipv6 = sgw_self()->gtpc_addr6;
/* Set IMSI */
sgw_ue->imsi_len = imsi_len;
@ -535,7 +674,8 @@ sgw_sess_t *sgw_sess_add(
d_assert(sess, return NULL, "Null param");
sess->sgw_s5c_teid = SGW_S5C_INDEX_TO_TEID(sess->index);
sess->sgw_s5c_addr = sgw_self()->gtpc_addr;
sess->sgw_s5c_ipv4 = sgw_self()->gtpc_addr;
sess->sgw_s5c_ipv6 = sgw_self()->gtpc_addr6;
/* Set APN */
core_cpystrn(sess->pdn.apn, apn, MAX_APN_LEN+1);

View File

@ -20,9 +20,12 @@ typedef struct _sgw_tunnel_t sgw_tunnel_t;
typedef struct _gtp_node_t gtp_node_t;
typedef struct _sgw_context_t {
c_uint32_t gtpc_addr; /* GTP-U local address */
c_uint32_t gtpc_port; /* GTP-U local port */
sock_id gtpc_sock; /* GTP-U local listen socket */
c_uint32_t gtpc_port; /* Default GTPC 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 */
@ -44,7 +47,8 @@ typedef struct _sgw_ue_t {
/* IMPORTANT!
* SGW-S11-F-TEID is same with an index */
c_uint32_t sgw_s11_teid;
c_uint32_t sgw_s11_addr;
c_sockaddr_t *sgw_s11_ipv4; /* SGW S11 IPv4 Address */
c_sockaddr_t *sgw_s11_ipv6; /* SGW S11 IPv6 Address */
c_uint32_t mme_s11_teid; /* MME-S11-F-TEID */
c_uint32_t mme_s11_addr; /* MME-S11-F-TEID IPv4 Address */
@ -85,7 +89,8 @@ typedef struct _sgw_sess_t {
#define SGW_S5C_TEID_TO_INDEX(__iNDEX) (__iNDEX & ~0x80000000)
#define SGW_S5C_INDEX_TO_TEID(__iNDEX) (__iNDEX | 0x80000000)
c_uint32_t sgw_s5c_teid;
c_uint32_t sgw_s5c_addr;
c_sockaddr_t *sgw_s5c_ipv4; /* SGW S5C IPv4 Address */
c_sockaddr_t *sgw_s5c_ipv6; /* SGW S5C IPv6 Address */
c_uint32_t pgw_s5c_teid; /* PGW-S5C-F-TEID */
c_uint32_t pgw_s5c_addr; /* PGW-S5C-F-TEID IPv4 Address */

View File

@ -228,15 +228,53 @@ static int _gtpv1_u_recv_cb(sock_id sock, void *data)
status_t sgw_gtp_open()
{
status_t rv;
sock_node_t *snode;
rv = gtp_listen(&sgw_self()->gtpc_sock, _gtpv2_c_recv_cb,
sgw_self()->gtpc_addr, sgw_self()->gtpc_port, NULL);
if (rv != CORE_OK)
for (snode = list_first(&sgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
d_error("Can't establish GTP-C Path for MME/PGW");
return rv;
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_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;
}
}
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)
@ -252,11 +290,18 @@ status_t sgw_gtp_close()
{
status_t rv;
rv = gtp_close(sgw_self()->gtpc_sock);
if (rv != CORE_OK)
sock_node_t *snode;
for (snode = list_first(&sgw_self()->gtpc_list);
snode; snode = list_next(snode))
{
d_error("Can't close GTP-C Path for MME/PGW");
return rv;
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);

View File

@ -23,6 +23,7 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
pkbuf_t *pkbuf = NULL;
gtp_f_teid_t *mme_s11_teid = NULL;
gtp_f_teid_t *pgw_s5c_teid = NULL;
int len = 0;
gtp_node_t *pgw = NULL;
gtp_f_teid_t sgw_s5c_teid, sgw_s5u_teid;
gtp_uli_t uli;
@ -88,13 +89,14 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
/* Send Control Plane(DL) : SGW-S5C */
memset(&sgw_s5c_teid, 0, sizeof(gtp_f_teid_t));
sgw_s5c_teid.teid = htonl(sess->sgw_s5c_teid);
sgw_s5c_teid.ipv4 = 1;
sgw_s5c_teid.ip.addr = sess->sgw_s5c_addr;
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(
sess->sgw_s5c_ipv4, sess->sgw_s5c_ipv6, &sgw_s5c_teid, &len);
d_assert(rv == CORE_OK, 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 = GTP_F_TEID_IPV4_LEN;
req->sender_f_teid_for_control_plane.len = len;
pgw_s5c_teid = req->pgw_s5_s8_address_for_control_plane_or_pmip.data;
d_assert(pgw_s5c_teid, return, "Null param");

View File

@ -3,6 +3,7 @@
#include "core_debug.h"
#include "core_lib.h"
#include "gtp_conv.h"
#include "gtp_types.h"
#include "sgw_event.h"
@ -25,6 +26,7 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
gtp_f_teid_t sgw_s11_teid;
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;
@ -84,13 +86,14 @@ void sgw_s5c_handle_create_session_response(gtp_xact_t *s5c_xact,
/* Send Control Plane(UL) : SGW-S11 */
memset(&sgw_s11_teid, 0, sizeof(gtp_f_teid_t));
sgw_s11_teid.ipv4 = 1;
sgw_s11_teid.interface_type = GTP_F_TEID_S11_S4_SGW_GTP_C;
sgw_s11_teid.ip.addr = sgw_ue->sgw_s11_addr;
sgw_s11_teid.teid = htonl(sgw_ue->sgw_s11_teid);
rv = gtp_sockaddr_to_f_teid(
sgw_ue->sgw_s11_ipv4, sgw_ue->sgw_s11_ipv6, &sgw_s11_teid, &len);
d_assert(rv == CORE_OK, 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 = GTP_F_TEID_IPV4_LEN;
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));