From 10675caf895845f743b28d622969a2de284135eb Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 2 Jun 2019 21:55:24 +0900 Subject: [PATCH] Add SGsAP configuration --- lib/base/types.h | 3 + lib/nas/nas_types.h | 4 + src/mme/emm_handler.c | 20 +-- src/mme/mme_context.c | 292 ++++++++++++++++++++++++++++++++++++----- src/mme/mme_context.h | 29 +++- src/mme/s1ap_handler.c | 82 ++++++------ 6 files changed, 344 insertions(+), 86 deletions(-) diff --git a/lib/base/types.h b/lib/base/types.h index 784b5cb9e7..c5fc0c5d90 100644 --- a/lib/base/types.h +++ b/lib/base/types.h @@ -29,12 +29,15 @@ extern "C" { #define S1AP_SCTP_PORT 36412 #define GTPV2_C_UDP_PORT 2123 #define GTPV1_U_UDP_PORT 2152 +#define SGSAP_SCTP_PORT 29118 #define SCTP_S1AP_PPID 18 #define SCTP_X2AP_PPID 27 +#define SCTP_SGSAP_PPID 0 #define MAX_NUM_OF_SGW 32 #define MAX_NUM_OF_PGW 32 +#define MAX_NUM_OF_VLR 32 #define MAX_NUM_OF_ENB 128 #define MAX_NUM_OF_UE 128 diff --git a/lib/nas/nas_types.h b/lib/nas/nas_types.h index 78b7b57f1e..a8ca4d00f7 100644 --- a/lib/nas/nas_types.h +++ b/lib/nas/nas_types.h @@ -118,6 +118,8 @@ typedef struct nas_location_area_identification_s { uint16_t lac; } __attribute__ ((packed)) nas_location_area_identification_t; +typedef nas_location_area_identification_t nas_lai_t; + /* 9.9.2.3 Mobile identity * See subclause 10.5.1.4 in 3GPP TS 24.008 [13]. * O TLV 7-10 */ @@ -780,6 +782,8 @@ typedef struct nas_tracking_area_identity_s { uint16_t tac; } __attribute__ ((packed)) nas_tracking_area_identity_t; +typedef nas_tracking_area_identity_t nas_tai_t; + /* 9.9.3.33 Tracking area identity list * M LV 7-97 */ #define NAS_MAX_TAI_LIST_LEN 96 diff --git a/src/mme/emm_handler.c b/src/mme/emm_handler.c index 5320bbbad0..d513fbd268 100644 --- a/src/mme/emm_handler.c +++ b/src/mme/emm_handler.c @@ -70,14 +70,14 @@ int emm_handle_attach_request( ogs_debug(" OLD E_CGI[PLMN_ID:%06x,CELL_ID:%d]", plmn_id_hexdump(&mme_ue->e_cgi.plmn_id), mme_ue->e_cgi.cell_id); ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]", - plmn_id_hexdump(&enb_ue->nas.tai.plmn_id), enb_ue->nas.tai.tac); + plmn_id_hexdump(&enb_ue->saved.tai.plmn_id), enb_ue->saved.tai.tac); ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:%d]", - plmn_id_hexdump(&enb_ue->nas.e_cgi.plmn_id), - enb_ue->nas.e_cgi.cell_id); + plmn_id_hexdump(&enb_ue->saved.e_cgi.plmn_id), + enb_ue->saved.e_cgi.cell_id); /* Copy TAI and ECGI from enb_ue */ - memcpy(&mme_ue->tai, &enb_ue->nas.tai, sizeof(tai_t)); - memcpy(&mme_ue->e_cgi, &enb_ue->nas.e_cgi, sizeof(e_cgi_t)); + memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(tai_t)); + memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(e_cgi_t)); /* Check TAI */ served_tai_index = mme_find_served_tai(&mme_ue->tai); @@ -440,14 +440,14 @@ int emm_handle_tau_request( ogs_debug(" OLD E_CGI[PLMN_ID:%06x,CELL_ID:%d]", plmn_id_hexdump(&mme_ue->e_cgi.plmn_id), mme_ue->e_cgi.cell_id); ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]", - plmn_id_hexdump(&enb_ue->nas.tai.plmn_id), enb_ue->nas.tai.tac); + plmn_id_hexdump(&enb_ue->saved.tai.plmn_id), enb_ue->saved.tai.tac); ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:%d]", - plmn_id_hexdump(&enb_ue->nas.e_cgi.plmn_id), - enb_ue->nas.e_cgi.cell_id); + plmn_id_hexdump(&enb_ue->saved.e_cgi.plmn_id), + enb_ue->saved.e_cgi.cell_id); /* Copy TAI and ECGI from enb_ue */ - memcpy(&mme_ue->tai, &enb_ue->nas.tai, sizeof(tai_t)); - memcpy(&mme_ue->e_cgi, &enb_ue->nas.e_cgi, sizeof(e_cgi_t)); + memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(tai_t)); + memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(e_cgi_t)); /* Check TAI */ served_tai_index = mme_find_served_tai(&mme_ue->tai); diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index 21eecfdc22..62ce8dd112 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -28,6 +28,7 @@ int __esm_log_domain; static OGS_POOL(mme_sgw_pool, mme_sgw_t); static OGS_POOL(mme_pgw_pool, mme_pgw_t); +static OGS_POOL(mme_vlr_pool, mme_vlr_t); static OGS_POOL(mme_enb_pool, mme_enb_t); static OGS_POOL(mme_ue_pool, mme_ue_t); @@ -61,9 +62,11 @@ void mme_context_init() gtp_node_init(); ogs_list_init(&self.sgw_list); ogs_list_init(&self.pgw_list); + ogs_list_init(&self.vlr_list); ogs_pool_init(&mme_sgw_pool, MAX_NUM_OF_SGW); ogs_pool_init(&mme_pgw_pool, MAX_NUM_OF_PGW); + ogs_pool_init(&mme_vlr_pool, MAX_NUM_OF_VLR); ogs_pool_init(&mme_enb_pool, MAX_NUM_OF_ENB); @@ -95,6 +98,7 @@ void mme_context_final() mme_sgw_remove_all(); mme_pgw_remove_all(); + mme_vlr_remove_all(); ogs_assert(self.enb_sock_hash); ogs_hash_destroy(self.enb_sock_hash); @@ -120,6 +124,7 @@ void mme_context_final() ogs_pool_final(&mme_sgw_pool); ogs_pool_final(&mme_pgw_pool); + ogs_pool_final(&mme_vlr_pool); gtp_node_final(); @@ -137,6 +142,7 @@ static int mme_context_prepare() self.s1ap_port = S1AP_SCTP_PORT; self.gtpc_port = GTPV2_C_UDP_PORT; + self.sgsap_port = SGSAP_SCTP_PORT; self.fd_config->cnf_port = DIAMETER_PORT; self.fd_config->cnf_port_tls = DIAMETER_SECURE_PORT; @@ -275,8 +281,7 @@ int mme_context_parse_config() } else if (!strcmp(fd_key, "listen_on")) { self.fd_config->cnf_addr = ogs_yaml_iter_value(&fd_iter); - } - else if (!strcmp(fd_key, "load_extension")) { + } else if (!strcmp(fd_key, "load_extension")) { ogs_yaml_iter_t ext_array, ext_iter; ogs_yaml_iter_recurse(&fd_iter, &ext_array); do { @@ -505,8 +510,8 @@ int mme_context_parse_config() } } else if (!strcmp(mme_key, "gtpc")) { ogs_yaml_iter_t gtpc_array, gtpc_iter; - ogs_yaml_iter_recurse(&mme_iter, >pc_array); do - { + ogs_yaml_iter_recurse(&mme_iter, >pc_array); + do { int family = AF_UNSPEC; int i, num = 0; const char *hostname[MAX_NUM_OF_HOSTNAME]; @@ -546,7 +551,8 @@ int mme_context_parse_config() } else if (!strcmp(gtpc_key, "addr") || !strcmp(gtpc_key, "name")) { ogs_yaml_iter_t hostname_iter; - ogs_yaml_iter_recurse(>pc_iter, &hostname_iter); + ogs_yaml_iter_recurse(>pc_iter, + &hostname_iter); ogs_assert(ogs_yaml_iter_type(&hostname_iter) != YAML_MAPPING_NODE); @@ -699,8 +705,7 @@ int mme_context_parse_config() } while (ogs_yaml_iter_type(&plmn_id_array) == YAML_SEQUENCE_NODE); - } - else if (!strcmp(gummei_key, "mme_gid")) { + } else if (!strcmp(gummei_key, "mme_gid")) { ogs_yaml_iter_t mme_gid_iter; ogs_yaml_iter_recurse(&gummei_iter, &mme_gid_iter); ogs_assert(ogs_yaml_iter_type(&mme_gid_iter) != @@ -989,8 +994,7 @@ int mme_context_parse_config() YAML_SEQUENCE_NODE); } } - } - else if (!strcmp(mme_key, "network_name")) { + } else if (!strcmp(mme_key, "network_name")) { ogs_yaml_iter_t network_name_iter; ogs_yaml_iter_recurse(&mme_iter, &network_name_iter); @@ -1032,21 +1036,209 @@ int mme_context_parse_config() network_short_name->coding_scheme = 1; } } + } else if (!strcmp(mme_key, "sgsap")) { + ogs_yaml_iter_t sgsap_array, sgsap_iter; + ogs_yaml_iter_recurse(&mme_iter, &sgsap_array); + do { + mme_vlr_t *vlr = NULL; + nas_tai_t tai; + const char *tai_mcc = NULL, *tai_mnc = NULL; + const char *tai_tac = NULL; + nas_lai_t lai; + const char *lai_mcc = NULL, *lai_mnc = NULL; + const char *lai_lac = NULL; + ogs_sockaddr_t *addr = NULL; + int family = AF_UNSPEC; + int i, num = 0; + const char *hostname[MAX_NUM_OF_HOSTNAME]; + uint16_t port = self.sgsap_port; + + if (ogs_yaml_iter_type(&sgsap_array) == + YAML_MAPPING_NODE) { + memcpy(&sgsap_iter, &sgsap_array, + sizeof(ogs_yaml_iter_t)); + } else if (ogs_yaml_iter_type(&sgsap_array) == + YAML_SEQUENCE_NODE) { + if (!ogs_yaml_iter_next(&sgsap_array)) + break; + ogs_yaml_iter_recurse(&sgsap_array, &sgsap_iter); + } else if (ogs_yaml_iter_type(&sgsap_array) == + YAML_SCALAR_NODE) { + break; + } else + ogs_assert_if_reached(); + + while (ogs_yaml_iter_next(&sgsap_iter)) { + const char *sgsap_key = + ogs_yaml_iter_key(&sgsap_iter); + ogs_assert(sgsap_key); + if (!strcmp(sgsap_key, "family")) { + const char *v = + ogs_yaml_iter_value(&sgsap_iter); + if (v) family = atoi(v); + if (family != AF_UNSPEC && + family != AF_INET && family != AF_INET6) { + ogs_warn("Ignore family(%d) : AF_UNSPEC(%d), " + "AF_INET(%d), AF_INET6(%d) ", + family, AF_UNSPEC, AF_INET, AF_INET6); + family = AF_UNSPEC; + } + } else if (!strcmp(sgsap_key, "addr") || + !strcmp(sgsap_key, "name")) { + ogs_yaml_iter_t hostname_iter; + ogs_yaml_iter_recurse(&sgsap_iter, + &hostname_iter); + ogs_assert(ogs_yaml_iter_type(&hostname_iter) != + YAML_MAPPING_NODE); + + do { + if (ogs_yaml_iter_type(&hostname_iter) == + YAML_SEQUENCE_NODE) { + if (!ogs_yaml_iter_next(&hostname_iter)) + break; + } + + ogs_assert(num <= MAX_NUM_OF_HOSTNAME); + hostname[num++] = + ogs_yaml_iter_value(&hostname_iter); + } while ( + ogs_yaml_iter_type(&hostname_iter) == + YAML_SEQUENCE_NODE); + } else if (!strcmp(sgsap_key, "port")) { + const char *v = ogs_yaml_iter_value(&sgsap_iter); + if (v) { + port = atoi(v); + self.sgsap_port = port; + } + } else if (!strcmp(sgsap_key, "tai")) { + ogs_yaml_iter_t tai_iter; + ogs_yaml_iter_recurse(&sgsap_iter, &tai_iter); + + while (ogs_yaml_iter_next(&tai_iter)) { + const char *tai_key = + ogs_yaml_iter_key(&tai_iter); + ogs_assert(tai_key); + if (!strcmp(tai_key, "plmn_id")) { + ogs_yaml_iter_t plmn_id_iter; + ogs_yaml_iter_recurse(&tai_iter, + &plmn_id_iter); + while (ogs_yaml_iter_next( + &plmn_id_iter)) { + const char *plmn_id_key = + ogs_yaml_iter_key( + &plmn_id_iter); + ogs_assert(plmn_id_key); + if (!strcmp(plmn_id_key, "mcc")) { + tai_mcc = ogs_yaml_iter_value( + &plmn_id_iter); + } else if (!strcmp(plmn_id_key, + "mnc")) { + tai_mnc = ogs_yaml_iter_value( + &plmn_id_iter); + } + } + } else if (!strcmp(tai_key, "tac")) { + tai_tac = + ogs_yaml_iter_value(&tai_iter); + } else + ogs_warn("unknown key `%s`", tai_key); + } + } else if (!strcmp(sgsap_key, "lai")) { + ogs_yaml_iter_t tai_iter; + ogs_yaml_iter_recurse(&sgsap_iter, &tai_iter); + + while (ogs_yaml_iter_next(&tai_iter)) { + const char *tai_key = + ogs_yaml_iter_key(&tai_iter); + ogs_assert(tai_key); + if (!strcmp(tai_key, "plmn_id")) { + ogs_yaml_iter_t plmn_id_iter; + ogs_yaml_iter_recurse(&tai_iter, + &plmn_id_iter); + while (ogs_yaml_iter_next( + &plmn_id_iter)) { + const char *plmn_id_key = + ogs_yaml_iter_key( + &plmn_id_iter); + ogs_assert(plmn_id_key); + if (!strcmp(plmn_id_key, "mcc")) { + lai_mcc = ogs_yaml_iter_value( + &plmn_id_iter); + } else if (!strcmp(plmn_id_key, + "mnc")) { + lai_mnc = ogs_yaml_iter_value( + &plmn_id_iter); + } + } + } else if (!strcmp(tai_key, "lac")) { + lai_lac = + ogs_yaml_iter_value(&tai_iter); + } else + ogs_warn("unknown key `%s`", tai_key); + } + } else + ogs_warn("unknown key `%s`", sgsap_key); + } + + if (tai_mcc && tai_mnc && tai_tac) { + plmn_id_t plmn_id; + plmn_id_build(&plmn_id, + atoi(tai_mcc), atoi(tai_mnc), strlen(tai_mnc)); + nas_from_plmn_id(&tai.plmn_id, &plmn_id); + tai.tac = atoi(tai_tac); + } else { + ogs_error("sgsap.tai configuration failed" + " - (mcc:%p, mnc:%p, tac:%p)", + tai_mcc, tai_mnc, tai_tac); + return OGS_ERROR; + } + + if (lai_mcc && lai_mnc && lai_lac) { + plmn_id_t plmn_id; + plmn_id_build(&plmn_id, + atoi(lai_mcc), atoi(lai_mnc), strlen(lai_mnc)); + nas_from_plmn_id(&tai.plmn_id, &plmn_id); + lai.lac = atoi(lai_lac); + } else { + ogs_error("sgsap.lai configuration failed" + " - (mcc:%p, mnc:%p, lac:%p)", + lai_mcc, lai_mnc, lai_lac); + return OGS_ERROR; + } + addr = NULL; + for (i = 0; i < num; i++) { + rv = ogs_addaddrinfo(&addr, + family, hostname[i], port, 0); + ogs_assert(rv == OGS_OK); + } + vlr = mme_vlr_add(addr, + context_self()->config.parameter.no_ipv4, + context_self()->config.parameter.no_ipv6, + context_self()->config.parameter.prefer_ipv4); + ogs_assert(vlr); + + memcpy(&vlr->tai, &tai, sizeof tai); + memcpy(&vlr->lai, &lai, sizeof lai); + + ogs_freeaddrinfo(addr); + + } while (ogs_yaml_iter_type(&sgsap_array) == + YAML_SEQUENCE_NODE); } else ogs_warn("unknown key `%s`", mme_key); } } else if (!strcmp(root_key, "sgw")) { - ogs_yaml_iter_t mme_iter; - ogs_yaml_iter_recurse(&root_iter, &mme_iter); - while (ogs_yaml_iter_next(&mme_iter)) { - const char *mme_key = ogs_yaml_iter_key(&mme_iter); + ogs_yaml_iter_t sgw_iter; + ogs_yaml_iter_recurse(&root_iter, &sgw_iter); + while (ogs_yaml_iter_next(&sgw_iter)) { + const char *mme_key = ogs_yaml_iter_key(&sgw_iter); ogs_assert(mme_key); if (!strcmp(mme_key, "gtpc")) { ogs_yaml_iter_t gtpc_array, gtpc_iter; - ogs_yaml_iter_recurse(&mme_iter, >pc_array); + ogs_yaml_iter_recurse(&sgw_iter, >pc_array); do { mme_sgw_t *sgw = NULL; - ogs_sockaddr_t *list = NULL; + ogs_sockaddr_t *addr = NULL; int family = AF_UNSPEC; int i, num = 0; const char *hostname[MAX_NUM_OF_HOSTNAME]; @@ -1136,14 +1328,14 @@ int mme_context_parse_config() ogs_warn("unknown key `%s`", gtpc_key); } - list = NULL; + addr = NULL; for (i = 0; i < num; i++) { - rv = ogs_addaddrinfo(&list, + rv = ogs_addaddrinfo(&addr, family, hostname[i], port, 0); ogs_assert(rv == OGS_OK); } - sgw = mme_sgw_add(list, + sgw = mme_sgw_add(addr, context_self()->config.parameter.no_ipv4, context_self()->config.parameter.no_ipv6, context_self()->config.parameter.prefer_ipv4); @@ -1151,13 +1343,13 @@ int mme_context_parse_config() if (num_of_tac != 0) memcpy(sgw->tac, tac, sizeof(sgw->tac)); - ogs_freeaddrinfo(list); + ogs_freeaddrinfo(addr); } while (ogs_yaml_iter_type(>pc_array) == YAML_SEQUENCE_NODE); } else if(!strcmp(mme_key, "selection_mode")) { const char *selection_mode = - ogs_yaml_iter_value(&mme_iter); + ogs_yaml_iter_value(&sgw_iter); if (!strcmp(selection_mode, "rr")) self.sgw_selection = SGW_SELECT_RR; @@ -1169,17 +1361,17 @@ int mme_context_parse_config() } } } else if (!strcmp(root_key, "pgw")) { - ogs_yaml_iter_t mme_iter; - ogs_yaml_iter_recurse(&root_iter, &mme_iter); - while (ogs_yaml_iter_next(&mme_iter)) { - const char *mme_key = ogs_yaml_iter_key(&mme_iter); + ogs_yaml_iter_t pgw_iter; + ogs_yaml_iter_recurse(&root_iter, &pgw_iter); + while (ogs_yaml_iter_next(&pgw_iter)) { + const char *mme_key = ogs_yaml_iter_key(&pgw_iter); ogs_assert(mme_key); if (!strcmp(mme_key, "gtpc")) { ogs_yaml_iter_t gtpc_array, gtpc_iter; - ogs_yaml_iter_recurse(&mme_iter, >pc_array); + ogs_yaml_iter_recurse(&pgw_iter, >pc_array); do { mme_pgw_t *pgw = NULL; - ogs_sockaddr_t *list = NULL; + ogs_sockaddr_t *addr = NULL; int family = AF_UNSPEC; int i, num = 0; const char *hostname[MAX_NUM_OF_HOSTNAME]; @@ -1244,20 +1436,20 @@ int mme_context_parse_config() ogs_warn("unknown key `%s`", gtpc_key); } - list = NULL; + addr = NULL; for (i = 0; i < num; i++) { - rv = ogs_addaddrinfo(&list, + rv = ogs_addaddrinfo(&addr, family, hostname[i], port, 0); ogs_assert(rv == OGS_OK); } - pgw = mme_pgw_add(list, + pgw = mme_pgw_add(addr, context_self()->config.parameter.no_ipv4, context_self()->config.parameter.no_ipv6, context_self()->config.parameter.prefer_ipv4); pgw->apn = apn; - ogs_freeaddrinfo(list); + ogs_freeaddrinfo(addr); } while (ogs_yaml_iter_type(>pc_array) == YAML_SEQUENCE_NODE); @@ -1363,6 +1555,44 @@ ogs_sockaddr_t *mme_pgw_addr_find_by_apn( return NULL; } +mme_vlr_t *mme_vlr_add( + ogs_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4) +{ + mme_vlr_t *vlr = NULL; + + ogs_assert(all_list); + + ogs_pool_alloc(&mme_vlr_pool, &vlr); + ogs_assert(vlr); + memset(vlr, 0, sizeof *vlr); + +#if 0 + vlr->gnode = gtp_node_new(all_list, no_ipv4, no_ipv6, prefer_ipv4); +#endif + ogs_list_add(&self.vlr_list, vlr); + + return vlr; +} + +void mme_vlr_remove(mme_vlr_t *vlr) +{ + ogs_assert(vlr); + + ogs_list_remove(&self.vlr_list, vlr); + +#if 0 + gtp_node_free(vlr->gnode); +#endif + ogs_pool_free(&mme_vlr_pool, vlr); +} + +void mme_vlr_remove_all() +{ + mme_vlr_t *vlr = NULL, *next_vlr = NULL; + + ogs_list_for_each_safe(&self.vlr_list, next_vlr, vlr) + mme_vlr_remove(vlr); +} mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr) { @@ -1712,7 +1942,7 @@ mme_ue_t* mme_ue_add(enb_ue_t *enb_ue) mme_self()->sgw = ogs_list_first(&mme_self()->sgw_list); while (mme_self()->sgw && !found) { for (i = 0; i < mme_self()->sgw->num_of_tac && !found; i++) - found = mme_self()->sgw->tac[i] == enb_ue->nas.tai.tac ? 1: 0; + found = mme_self()->sgw->tac[i] == enb_ue->saved.tai.tac ? 1: 0; if (!found) mme_self()->sgw = ogs_list_next(mme_self()->sgw); diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index 5414773655..396aaa83ea 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -35,6 +35,7 @@ extern int __esm_log_domain; typedef struct mme_sgw_s mme_sgw_t; typedef struct mme_pgw_s mme_pgw_t; +typedef struct mme_vlr_s mme_vlr_t; typedef struct enb_ue_s enb_ue_t; typedef struct mme_ue_s mme_ue_t; @@ -67,14 +68,15 @@ typedef struct mme_context_s { uint16_t s1ap_port; /* Default S1AP Port */ uint16_t gtpc_port; /* Default GTPC Port */ + uint16_t sgsap_port; /* Default SGsAP Port */ ogs_list_t s1ap_list; /* MME S1AP IPv4 Server List */ ogs_list_t s1ap_list6; /* MME S1AP IPv6 Server List */ ogs_list_t gtpc_list; /* MME GTPC IPv4 Server List */ ogs_list_t gtpc_list6; /* MME GTPC IPv6 Server List */ - ogs_sock_t *gtpc_sock; /* MME GTPC IPv4 Socket */ - ogs_sock_t *gtpc_sock6; /* MME GTPC IPv6 Socket */ + ogs_sock_t *gtpc_sock; /* MME GTPC IPv4 Socket */ + ogs_sock_t *gtpc_sock6; /* MME GTPC IPv6 Socket */ ogs_sockaddr_t *gtpc_addr; /* MME GTPC IPv4 Address */ ogs_sockaddr_t *gtpc_addr6; /* MME GTPC IPv6 Address */ @@ -85,6 +87,9 @@ typedef struct mme_context_s { ogs_sockaddr_t *pgw_addr; /* First IPv4 Address Selected */ ogs_sockaddr_t *pgw_addr6; /* First IPv6 Address Selected */ + ogs_list_t vlr_list; /* VLR SGsAP Client List */ + mme_vlr_t *vlr; /* Iterator for VLR */ + /* Served GUMME */ uint8_t max_num_of_served_gummei; served_gummei_t served_gummei[MAX_NUM_OF_SERVED_GUMMEI]; @@ -161,8 +166,17 @@ typedef struct mme_pgw_s { const char *apn; } mme_pgw_t; +typedef struct mme_vlr_s { + ogs_lnode_t lnode; + + nas_tai_t tai; + nas_lai_t lai; + + ogs_socknode_t *node; +} mme_vlr_t; + typedef struct mme_enb_s { - ogs_fsm_t sm; /* A state machine */ + ogs_fsm_t sm; /* A state machine */ uint32_t enb_id; /* eNB_ID received from eNB */ int sock_type; /* SOCK_STREAM or SOCK_SEQPACKET */ @@ -193,13 +207,13 @@ struct enb_ue_s { enb_ue_t *target_ue; /* Use mme_ue->tai, mme_ue->e_cgi. - * Do not access enb_ue->nas.tai enb_ue->nas.e_cgi. + * Do not access enb_ue->saved.tai enb_ue->saved.e_cgi. * * Save TAI and ECGI. And then, this will copy 'mme_ue_t' context later */ struct { tai_t tai; e_cgi_t e_cgi; - } nas; + } saved; /* Store by UE Context Release Command * Retrieve by UE Context Release Complete */ @@ -518,6 +532,11 @@ void mme_pgw_remove_all(); ogs_sockaddr_t *mme_pgw_addr_find_by_apn( ogs_list_t *list, int family, char *apn); +mme_vlr_t *mme_vlr_add( + ogs_sockaddr_t *all_list, int no_ipv4, int no_ipv6, int prefer_ipv4); +void mme_vlr_remove(mme_vlr_t *vlr); +void mme_vlr_remove_all(); + mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr); int mme_enb_remove(mme_enb_t *enb); int mme_enb_remove_all(void); diff --git a/src/mme/s1ap_handler.c b/src/mme/s1ap_handler.c index 9e21841d78..1e534e0bb3 100644 --- a/src/mme/s1ap_handler.c +++ b/src/mme/s1ap_handler.c @@ -284,24 +284,24 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message) tAC = &TAI->tAC; ogs_assert(tAC && tAC->size == sizeof(uint16_t)); - memcpy(&enb_ue->nas.tai.plmn_id, pLMNidentity->buf, - sizeof(enb_ue->nas.tai.plmn_id)); - memcpy(&enb_ue->nas.tai.tac, tAC->buf, sizeof(enb_ue->nas.tai.tac)); - enb_ue->nas.tai.tac = ntohs(enb_ue->nas.tai.tac); + memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, + sizeof(enb_ue->saved.tai.plmn_id)); + memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); + enb_ue->saved.tai.tac = ntohs(enb_ue->saved.tai.tac); ogs_assert(EUTRAN_CGI); pLMNidentity = &EUTRAN_CGI->pLMNidentity; ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(plmn_id_t)); cell_ID = &EUTRAN_CGI->cell_ID; ogs_assert(cell_ID); - memcpy(&enb_ue->nas.e_cgi.plmn_id, pLMNidentity->buf, - sizeof(enb_ue->nas.e_cgi.plmn_id)); - memcpy(&enb_ue->nas.e_cgi.cell_id, cell_ID->buf, - sizeof(enb_ue->nas.e_cgi.cell_id)); - enb_ue->nas.e_cgi.cell_id = (ntohl(enb_ue->nas.e_cgi.cell_id) >> 4); + memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, + sizeof(enb_ue->saved.e_cgi.plmn_id)); + memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf, + sizeof(enb_ue->saved.e_cgi.cell_id)); + enb_ue->saved.e_cgi.cell_id = (ntohl(enb_ue->saved.e_cgi.cell_id) >> 4); ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d] TAC[%d]", - enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id, enb_ue->nas.tai.tac); + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id, enb_ue->saved.tai.tac); ogs_assert(s1ap_send_to_nas(enb_ue, S1AP_ProcedureCode_id_initialUEMessage, NAS_PDU) == OGS_OK); @@ -1165,16 +1165,16 @@ void s1ap_handle_path_switch_request( enb_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID; - memcpy(&enb_ue->nas.tai.plmn_id, pLMNidentity->buf, - sizeof(enb_ue->nas.tai.plmn_id)); - memcpy(&enb_ue->nas.tai.tac, tAC->buf, sizeof(enb_ue->nas.tai.tac)); - enb_ue->nas.tai.tac = ntohs(enb_ue->nas.tai.tac); + memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, + sizeof(enb_ue->saved.tai.plmn_id)); + memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); + enb_ue->saved.tai.tac = ntohs(enb_ue->saved.tai.tac); - memcpy(&enb_ue->nas.e_cgi.plmn_id, pLMNidentity->buf, - sizeof(enb_ue->nas.e_cgi.plmn_id)); - memcpy(&enb_ue->nas.e_cgi.cell_id, cell_ID->buf, - sizeof(enb_ue->nas.e_cgi.cell_id)); - enb_ue->nas.e_cgi.cell_id = (ntohl(enb_ue->nas.e_cgi.cell_id) >> 4); + memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, + sizeof(enb_ue->saved.e_cgi.plmn_id)); + memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf, + sizeof(enb_ue->saved.e_cgi.cell_id)); + enb_ue->saved.e_cgi.cell_id = (ntohl(enb_ue->saved.e_cgi.cell_id) >> 4); ogs_debug(" OLD TAI[PLMN_ID:%06x,TAC:%d]", plmn_id_hexdump(&mme_ue->tai.plmn_id), @@ -1183,15 +1183,15 @@ void s1ap_handle_path_switch_request( plmn_id_hexdump(&mme_ue->e_cgi.plmn_id), mme_ue->e_cgi.cell_id); ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]", - plmn_id_hexdump(&enb_ue->nas.tai.plmn_id), - enb_ue->nas.tai.tac); + plmn_id_hexdump(&enb_ue->saved.tai.plmn_id), + enb_ue->saved.tai.tac); ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:%d]", - plmn_id_hexdump(&enb_ue->nas.e_cgi.plmn_id), - enb_ue->nas.e_cgi.cell_id); + plmn_id_hexdump(&enb_ue->saved.e_cgi.plmn_id), + enb_ue->saved.e_cgi.cell_id); /* Copy TAI and ECGI from enb_ue */ - memcpy(&mme_ue->tai, &enb_ue->nas.tai, sizeof(tai_t)); - memcpy(&mme_ue->e_cgi, &enb_ue->nas.e_cgi, sizeof(e_cgi_t)); + memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(tai_t)); + memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(e_cgi_t)); memcpy(&eea, encryptionAlgorithms->buf, sizeof(eea)); eea = ntohs(eea); @@ -1904,16 +1904,18 @@ void s1ap_handle_handover_notification(mme_enb_t *enb, s1ap_message_t *message) mme_ue_associate_enb_ue(mme_ue, target_ue); - memcpy(&target_ue->nas.tai.plmn_id, pLMNidentity->buf, - sizeof(target_ue->nas.tai.plmn_id)); - memcpy(&target_ue->nas.tai.tac, tAC->buf, sizeof(target_ue->nas.tai.tac)); - target_ue->nas.tai.tac = ntohs(target_ue->nas.tai.tac); + memcpy(&target_ue->saved.tai.plmn_id, pLMNidentity->buf, + sizeof(target_ue->saved.tai.plmn_id)); + memcpy(&target_ue->saved.tai.tac, + tAC->buf, sizeof(target_ue->saved.tai.tac)); + target_ue->saved.tai.tac = ntohs(target_ue->saved.tai.tac); - memcpy(&target_ue->nas.e_cgi.plmn_id, pLMNidentity->buf, - sizeof(target_ue->nas.e_cgi.plmn_id)); - memcpy(&target_ue->nas.e_cgi.cell_id, cell_ID->buf, - sizeof(target_ue->nas.e_cgi.cell_id)); - target_ue->nas.e_cgi.cell_id = (ntohl(target_ue->nas.e_cgi.cell_id) >> 4); + memcpy(&target_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, + sizeof(target_ue->saved.e_cgi.plmn_id)); + memcpy(&target_ue->saved.e_cgi.cell_id, cell_ID->buf, + sizeof(target_ue->saved.e_cgi.cell_id)); + target_ue->saved.e_cgi.cell_id = + (ntohl(target_ue->saved.e_cgi.cell_id) >> 4); ogs_debug(" OLD TAI[PLMN_ID:%06x,TAC:%d]", plmn_id_hexdump(&mme_ue->tai.plmn_id), @@ -1922,15 +1924,15 @@ void s1ap_handle_handover_notification(mme_enb_t *enb, s1ap_message_t *message) plmn_id_hexdump(&mme_ue->e_cgi.plmn_id), mme_ue->e_cgi.cell_id); ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]", - plmn_id_hexdump(&target_ue->nas.tai.plmn_id), - target_ue->nas.tai.tac); + plmn_id_hexdump(&target_ue->saved.tai.plmn_id), + target_ue->saved.tai.tac); ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:%d]", - plmn_id_hexdump(&target_ue->nas.e_cgi.plmn_id), - target_ue->nas.e_cgi.cell_id); + plmn_id_hexdump(&target_ue->saved.e_cgi.plmn_id), + target_ue->saved.e_cgi.cell_id); /* Copy TAI and ECGI from enb_ue */ - memcpy(&mme_ue->tai, &target_ue->nas.tai, sizeof(tai_t)); - memcpy(&mme_ue->e_cgi, &target_ue->nas.e_cgi, sizeof(e_cgi_t)); + memcpy(&mme_ue->tai, &target_ue->saved.tai, sizeof(tai_t)); + memcpy(&mme_ue->e_cgi, &target_ue->saved.e_cgi, sizeof(e_cgi_t)); sess = mme_sess_first(mme_ue); while(sess)