[MME] add facility to select smf(pgwu) by tac and e_cell_id.

[mme.yaml]
# o SMF selection by eNodeB TAC
#   (either single TAC or multiple TACs, DECIMAL representation)
#
#   gtpc:
#     - addr: 127.0.0.4
#       tac: 26000
#     - addr: 127.0.2.4
#       tac: [25000, 27000, 28000]
#
# o SMF selection by e_cell_id(28bit)
#   (either single or multiple e_cell_id, HEX representation)
#
#   gtpc:
#     - addr: 127.0.0.4
#       e_cell_id: abcde01
#     - addr: 127.0.2.4
#       e_cell_id: [12345, a9413, 98765]
This commit is contained in:
Shigeru Ishida 2023-05-04 19:11:19 +09:00 committed by Sukchan Lee
parent 2a8a0b5e4a
commit 0c3fd10c24
5 changed files with 155 additions and 15 deletions

View File

@ -450,6 +450,24 @@ sgwc:
# - addr: 127.0.0.4
# - addr: 127.0.0.5
# apn: volte
#
# o SMF selection by eNodeB TAC
# (either single TAC or multiple TACs, DECIMAL representation)
#
# gtpc:
# - addr: 127.0.0.4
# tac: 26000
# - addr: 127.0.2.4
# tac: [25000, 27000, 28000]
#
# o SMF selection by e_cell_id(28bit)
# (either single or multiple e_cell_id, HEX representation)
#
# gtpc:
# - addr: 127.0.0.4
# e_cell_id: abcde01
# - addr: 127.0.2.4
# e_cell_id: [12345, a9413, 98765]
smf:
gtpc:
- addr:

View File

@ -1628,8 +1628,13 @@ int mme_context_parse_config(void)
int family = AF_UNSPEC;
int i, num = 0;
const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
const char *apn = NULL;
uint16_t port = ogs_gtp_self()->gtpc_port;
const char *apn[OGS_MAX_NUM_OF_APN] = {NULL,};
uint8_t num_of_apn = 0;
uint16_t tac[OGS_MAX_NUM_OF_TAI] = {0,};
uint8_t num_of_tac = 0;
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID] = {0,};
uint8_t num_of_e_cell_id = 0;
if (ogs_yaml_iter_type(&gtpc_array) ==
YAML_MAPPING_NODE) {
@ -1686,7 +1691,82 @@ int mme_context_parse_config(void)
const char *v = ogs_yaml_iter_value(&gtpc_iter);
if (v) port = atoi(v);
} else if (!strcmp(gtpc_key, "apn")) {
apn = ogs_yaml_iter_value(&gtpc_iter);
ogs_yaml_iter_t apn_iter;
ogs_yaml_iter_recurse(&gtpc_iter, &apn_iter);
ogs_assert(ogs_yaml_iter_type(&apn_iter) !=
YAML_MAPPING_NODE);
do {
const char *v = NULL;
ogs_assert(num_of_apn <
OGS_MAX_NUM_OF_APN);
if (ogs_yaml_iter_type(&apn_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&apn_iter))
break;
}
v = ogs_yaml_iter_value(&apn_iter);
if (v) {
apn[num_of_apn] = v;
num_of_apn++;
}
} while (
ogs_yaml_iter_type(&apn_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(gtpc_key, "tac")) {
ogs_yaml_iter_t tac_iter;
ogs_yaml_iter_recurse(&gtpc_iter, &tac_iter);
ogs_assert(ogs_yaml_iter_type(&tac_iter) !=
YAML_MAPPING_NODE);
do {
const char *v = NULL;
ogs_assert(num_of_tac <
OGS_MAX_NUM_OF_TAI);
if (ogs_yaml_iter_type(&tac_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&tac_iter))
break;
}
v = ogs_yaml_iter_value(&tac_iter);
if (v) {
tac[num_of_tac] = atoi(v);
num_of_tac++;
}
} while (
ogs_yaml_iter_type(&tac_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(gtpc_key, "e_cell_id")) {
ogs_yaml_iter_t e_cell_id_iter;
ogs_yaml_iter_recurse(&gtpc_iter,
&e_cell_id_iter);
ogs_assert(ogs_yaml_iter_type(&e_cell_id_iter)
!= YAML_MAPPING_NODE);
do {
const char *v = NULL;
ogs_assert(num_of_e_cell_id <
OGS_MAX_NUM_OF_CELL_ID);
if (ogs_yaml_iter_type(&e_cell_id_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(
&e_cell_id_iter))
break;
}
v = ogs_yaml_iter_value(&e_cell_id_iter);
if (v) {
e_cell_id[num_of_e_cell_id]
= ogs_uint64_from_string((char*)v);
num_of_e_cell_id++;
}
} while (
ogs_yaml_iter_type(&e_cell_id_iter) ==
YAML_SEQUENCE_NODE);
} else
ogs_warn("unknown key `%s`", gtpc_key);
}
@ -1708,7 +1788,18 @@ int mme_context_parse_config(void)
pgw = mme_pgw_add(addr);
ogs_assert(pgw);
pgw->apn = apn;
pgw->num_of_apn = num_of_apn;
if (num_of_apn != 0)
memcpy(pgw->apn, apn, sizeof(pgw->apn));
pgw->num_of_tac = num_of_tac;
if (num_of_tac != 0)
memcpy(pgw->tac, tac, sizeof(pgw->tac));
pgw->num_of_e_cell_id = num_of_e_cell_id;
if (num_of_e_cell_id != 0)
memcpy(pgw->e_cell_id, e_cell_id,
sizeof(pgw->e_cell_id));
} while (ogs_yaml_iter_type(&gtpc_array) ==
YAML_SEQUENCE_NODE);
@ -1881,8 +1972,33 @@ void mme_pgw_remove_all(void)
mme_pgw_remove(pgw);
}
ogs_sockaddr_t *mme_pgw_addr_find_by_apn(
ogs_list_t *list, int family, char *apn)
static bool compare_apn_enb_info(
mme_pgw_t *pgw, mme_sess_t *sess)
{
mme_ue_t *mme_ue = NULL;
int i;
ogs_assert(pgw);
ogs_assert(sess);
ogs_assert(sess->session);
ogs_assert(sess->session->name);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
for (i = 0; i < pgw->num_of_apn; i++)
if (!ogs_strcasecmp(pgw->apn[i], sess->session->name)) return true;
for (i = 0; i < pgw->num_of_e_cell_id; i++)
if (pgw->e_cell_id[i] == mme_ue->e_cgi.cell_id) return true;
for (i = 0; i < pgw->num_of_tac; i++)
if (pgw->tac[i] == mme_ue->tai.tac) return true;
return false;
}
ogs_sockaddr_t *mme_pgw_addr_find_by_apn_enb(
ogs_list_t *list, int family, mme_sess_t *sess)
{
mme_pgw_t *pgw = NULL;
ogs_assert(list);
@ -1893,7 +2009,7 @@ ogs_sockaddr_t *mme_pgw_addr_find_by_apn(
while (addr) {
if (addr->ogs_sa_family == family &&
(!apn || (pgw->apn && !ogs_strcasecmp(apn, pgw->apn)))) {
(!sess || compare_apn_enb_info(pgw, sess))) {
return addr;
}
addr = addr->next;

View File

@ -176,7 +176,13 @@ typedef struct mme_pgw_s {
ogs_lnode_t lnode;
ogs_sockaddr_t *sa_list;
const char *apn;
const char *apn[OGS_MAX_NUM_OF_APN];
uint8_t num_of_apn;
uint16_t tac[OGS_MAX_NUM_OF_TAI];
uint8_t num_of_tac;
uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID];
uint8_t num_of_e_cell_id;
} mme_pgw_t;
#define MME_SGSAP_IS_CONNECTED(__mME) \
@ -764,8 +770,8 @@ mme_sgw_t *mme_sgw_find_by_addr(ogs_sockaddr_t *addr);
mme_pgw_t *mme_pgw_add(ogs_sockaddr_t *addr);
void mme_pgw_remove(mme_pgw_t *pgw);
void mme_pgw_remove_all(void);
ogs_sockaddr_t *mme_pgw_addr_find_by_apn(
ogs_list_t *list, int family, char *apn);
ogs_sockaddr_t *mme_pgw_addr_find_by_apn_enb(
ogs_list_t *list, int family, mme_sess_t *sess);
mme_vlr_t *mme_vlr_add(ogs_sockaddr_t *sa_list, ogs_sockopt_t *option);
void mme_vlr_remove(mme_vlr_t *vlr);

View File

@ -179,9 +179,9 @@ int mme_gtp_open(void)
OGS_SETUP_GTPC_SERVER;
mme_self()->pgw_addr = mme_pgw_addr_find_by_apn(
mme_self()->pgw_addr = mme_pgw_addr_find_by_apn_enb(
&mme_self()->pgw_list, AF_INET, NULL);
mme_self()->pgw_addr6 = mme_pgw_addr_find_by_apn(
mme_self()->pgw_addr6 = mme_pgw_addr_find_by_apn_enb(
&mme_self()->pgw_list, AF_INET6, NULL);
ogs_assert(mme_self()->pgw_addr || mme_self()->pgw_addr6);

View File

@ -145,10 +145,10 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
ogs_sockaddr_t *pgw_addr = NULL;
ogs_sockaddr_t *pgw_addr6 = NULL;
pgw_addr = mme_pgw_addr_find_by_apn(
&mme_self()->pgw_list, AF_INET, session->name);
pgw_addr6 = mme_pgw_addr_find_by_apn(
&mme_self()->pgw_list, AF_INET6, session->name);
pgw_addr = mme_pgw_addr_find_by_apn_enb(
&mme_self()->pgw_list, AF_INET, sess);
pgw_addr6 = mme_pgw_addr_find_by_apn_enb(
&mme_self()->pgw_list, AF_INET6, sess);
if (!pgw_addr && !pgw_addr6) {
pgw_addr = mme_self()->pgw_addr;
pgw_addr6 = mme_self()->pgw_addr6;