diff --git a/lib/3gpp/3gpp_common.h b/lib/3gpp/3gpp_common.h index 59e621386..d6d024bad 100644 --- a/lib/3gpp/3gpp_common.h +++ b/lib/3gpp/3gpp_common.h @@ -7,12 +7,13 @@ extern "C" { #endif /* __cplusplus */ -#define MAX_NUM_OF_PDN 4 - #define MAX_UE_PER_ENB 128 #define MAX_NUM_OF_ENB 128 #define MAX_NUM_OF_UE (MAX_NUM_OF_ENB * MAX_UE_PER_ENB) +#define MAX_NUM_OF_PDN 4 +#define MAX_NUM_OF_UE_PDN (MAX_NUM_OF_UE * MAX_NUM_OF_PDN) + #define IPV6_LEN 16 #define MAX_SDU_LEN 2048 @@ -92,11 +93,10 @@ ED2(c_uint8_t spare:6;, /********************************** * PDN Structure */ -typedef c_uint32_t pdn_id_t; typedef struct _pdn_t { lnode_t node; /**< A node of list_t */ - pdn_id_t id; + c_uint32_t id; c_int8_t apn[MAX_APN_LEN]; #define S6A_PDN_TYPE_IPV4 0 #define S6A_PDN_TYPE_IPV6 1 @@ -135,6 +135,8 @@ typedef struct _pdn_t { #define PDN_PRE_EMPTION_VULNERABILITY_ENABLED 0 #define PDN_PRE_EMPTION_VULNERABILITY_DISABLED 1 c_uint8_t pre_emption_vulnerability; + + void *context; } pdn_t; /************************************************** diff --git a/src/hss/hss_context.c b/src/hss/hss_context.c index 75ec83a8b..b9e2ec105 100644 --- a/src/hss/hss_context.c +++ b/src/hss/hss_context.c @@ -27,6 +27,7 @@ status_t hss_context_init(void) hss_profile_t *profile; pdn_t *pdn; hss_ue_t *ue; + c_int8_t apn[MAX_APN_LEN]; memset(&self, 0, sizeof(hss_context_t)); @@ -62,11 +63,11 @@ status_t hss_context_init(void) /*********************************************** * PDN DB */ - pdn = hss_pdn_add(); - d_assert(pdn, return -1, "Profile context add failed"); + apn[0] = 0x08; + strcpy(apn+1, "internet"); - pdn->apn[0] = 0x08; - strcpy(pdn->apn+1, "internet"); + pdn = hss_pdn_add(apn); + d_assert(pdn, return -1, "PDN context add failed"); pdn->s6a_type = S6A_PDN_TYPE_IPV4; @@ -121,7 +122,7 @@ void hss_context_final(void) return; } -pdn_t* hss_pdn_add() +pdn_t* hss_pdn_add(c_int8_t *apn) { pdn_t *pdn = NULL; @@ -130,6 +131,7 @@ pdn_t* hss_pdn_add() memset(pdn, 0, sizeof(pdn_t)); + strcpy(pdn->apn, apn); pdn->id = NEXT_ID(self.pdn_id, 1, 0xffffffff); list_append(&self.pdn_list, pdn); @@ -164,14 +166,14 @@ status_t hss_pdn_remove_all() return CORE_OK; } -pdn_t* hss_pdn_find_by_id(pdn_id_t id) +pdn_t* hss_pdn_find_by_apn(c_int8_t *apn) { pdn_t *pdn = NULL; pdn = list_first(&self.pdn_list); while (pdn) { - if (pdn->id == id) + if (strcmp(pdn->apn, apn) == 0) break; pdn = list_next(pdn); diff --git a/src/hss/hss_context.h b/src/hss/hss_context.h index aa4c3937b..f0bc9f6ed 100644 --- a/src/hss/hss_context.h +++ b/src/hss/hss_context.h @@ -95,10 +95,10 @@ CORE_DECLARE(status_t) hss_context_init(void); CORE_DECLARE(void) hss_context_final(void); CORE_DECLARE(hss_context_t*) hss_self(void); -CORE_DECLARE(pdn_t*) hss_pdn_add(); +CORE_DECLARE(pdn_t*) hss_pdn_add(c_int8_t *apn); CORE_DECLARE(status_t) hss_pdn_remove(pdn_t *pdn); CORE_DECLARE(status_t) hss_pdn_remove_all(void); -CORE_DECLARE(pdn_t*) hss_pdn_find_by_id(pdn_id_t id); +CORE_DECLARE(pdn_t*) hss_pdn_find_by_apn(c_int8_t *apn); CORE_DECLARE(pdn_t*) hss_pdn_first(void); CORE_DECLARE(pdn_t*) hss_pdn_next(pdn_t *pdn); diff --git a/src/mme/esm_handler.c b/src/mme/esm_handler.c index 93d24611f..626f7384a 100644 --- a/src/mme/esm_handler.c +++ b/src/mme/esm_handler.c @@ -25,13 +25,18 @@ void esm_handle_pdn_connectivity_request(mme_esm_t *esm, void esm_handle_information_response(mme_esm_t *esm, nas_esm_information_response_t *esm_information_response) { + mme_ue_t *ue = NULL; pkbuf_t *pkbuf = NULL; status_t rv; + d_assert(esm, return, "Null param"); + ue = esm->ue; + d_assert(ue, return, "Null param"); + if (esm_information_response->presencemask & NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) { - esm->pdn = mme_pdn_find_by_apn( + esm->pdn = mme_pdn_find_by_apn(ue, esm_information_response->access_point_name.apn); d_assert(esm->pdn, return, "No PDN Context[APN:%s])", esm_information_response->access_point_name.apn); diff --git a/src/mme/mme_context.c b/src/mme/mme_context.c index d35e4cff2..e6ddbc555 100644 --- a/src/mme/mme_context.c +++ b/src/mme/mme_context.c @@ -14,6 +14,8 @@ #define MAX_NUM_OF_SGW 8 #define MAX_NUM_OF_ESM (MAX_NUM_OF_UE * MAX_ESM_PER_UE) +#define MME_NUM_OF_PDN (MAX_NUM_OF_UE * MAX_PDN_PER_UE) + #define S1AP_SCTP_PORT 36412 #define MIN_EPS_BEARER_ID 5 @@ -22,11 +24,11 @@ static mme_context_t self; pool_declare(mme_sgw_pool, mme_sgw_t, MAX_NUM_OF_SGW); -pool_declare(mme_pdn_pool, pdn_t, MAX_NUM_OF_PDN); index_declare(mme_enb_pool, mme_enb_t, MAX_NUM_OF_ENB); index_declare(mme_ue_pool, mme_ue_t, MAX_NUM_OF_UE); index_declare(mme_esm_pool, mme_esm_t, MAX_NUM_OF_ESM); +pool_declare(mme_pdn_pool, pdn_t, MAX_NUM_OF_UE_PDN); static int context_initialized = 0; @@ -41,14 +43,12 @@ status_t mme_context_init() pool_init(&mme_sgw_pool, MAX_NUM_OF_SGW); list_init(&self.sgw_list); - pool_init(&mme_pdn_pool, MAX_NUM_OF_PDN); - list_init(&self.pdn_list); - index_init(&mme_enb_pool, MAX_NUM_OF_ENB); list_init(&self.enb_list); index_init(&mme_ue_pool, MAX_NUM_OF_UE); index_init(&mme_esm_pool, MAX_NUM_OF_ESM); + pool_init(&mme_pdn_pool, MAX_NUM_OF_UE_PDN); self.mme_ue_s1ap_id_hash = hash_make(); @@ -94,17 +94,16 @@ status_t mme_context_final() mme_sgw_remove_all(); mme_enb_remove_all(); - mme_pdn_remove_all(); d_assert(self.mme_ue_s1ap_id_hash, , "Null param"); hash_destroy(self.mme_ue_s1ap_id_hash); + pool_final(&mme_pdn_pool); index_final(&mme_esm_pool); index_final(&mme_ue_pool); - index_final(&mme_enb_pool); + index_final(&mme_enb_pool); pool_final(&mme_sgw_pool); - pool_final(&mme_pdn_pool); context_initialized = 0; @@ -292,91 +291,6 @@ mme_enb_t* mme_enb_next(mme_enb_t *enb) return list_next(enb); } -pdn_t* mme_pdn_add(pdn_id_t id) -{ - pdn_t *pdn = NULL; - - pool_alloc_node(&mme_pdn_pool, &pdn); - d_assert(pdn, return NULL, "HSS-UE context allocation failed"); - - memset(pdn, 0, sizeof(pdn_t)); - - pdn->id = id; - - list_append(&self.pdn_list, pdn); - - return pdn; -} - -status_t mme_pdn_remove(pdn_t *pdn) -{ - d_assert(pdn, return CORE_ERROR, "Null param"); - - list_remove(&self.pdn_list, pdn); - pool_free_node(&mme_pdn_pool, pdn); - - return CORE_OK; -} - -status_t mme_pdn_remove_all() -{ - pdn_t *pdn = NULL, *next_pdn = NULL; - - pdn = list_first(&self.pdn_list); - while (pdn) - { - next_pdn = list_next(pdn); - - mme_pdn_remove(pdn); - - pdn = next_pdn; - } - - return CORE_OK; -} - -pdn_t* mme_pdn_find_by_id(pdn_id_t id) -{ - pdn_t *pdn = NULL; - - pdn = list_first(&self.pdn_list); - while (pdn) - { - if (pdn->id == id) - break; - - pdn = list_next(pdn); - } - - return pdn; -} - -pdn_t* mme_pdn_find_by_apn(c_int8_t *apn) -{ - pdn_t *pdn = NULL; - - pdn = list_first(&self.pdn_list); - while (pdn) - { - if (strcmp(pdn->apn, apn) == 0) - break; - - pdn = list_next(pdn); - } - - return pdn; -} - -pdn_t* mme_pdn_first() -{ - return list_first(&self.pdn_list); -} - -pdn_t* mme_pdn_next(pdn_t *pdn) -{ - return list_next(pdn); -} - mme_ue_t* mme_ue_add(mme_enb_t *enb) { mme_ue_t *ue = NULL; @@ -391,12 +305,14 @@ mme_ue_t* mme_ue_add(mme_enb_t *enb) hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id, sizeof(ue->mme_ue_s1ap_id), ue); + list_init(&ue->pdn_list); ue->ebi = MIN_EPS_BEARER_ID - 1; - ue->enb = enb; list_init(&ue->esm_list); list_append(&enb->ue_list, ue); + ue->enb = enb; + fsm_create(&ue->sm, emm_state_initial, emm_state_final); fsm_init(&ue->sm, 0); @@ -413,6 +329,7 @@ status_t mme_ue_remove(mme_ue_t *ue) fsm_clear(&ue->sm); mme_esm_remove_all(ue); + mme_pdn_remove_all(ue); list_remove(&ue->enb->ue_list, ue); hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id, @@ -613,3 +530,85 @@ mme_esm_t* mme_esm_next(mme_esm_t *esm) { return list_next(esm); } + +pdn_t* mme_pdn_add(mme_ue_t *ue, c_int8_t *apn) +{ + pdn_t *pdn = NULL; + + d_assert(ue, return NULL, "Null param"); + d_assert(apn, return NULL, "Null param"); + + pool_alloc_node(&mme_pdn_pool, &pdn); + d_assert(pdn, return NULL, "PDN context allocation failed"); + + memset(pdn, 0, sizeof(pdn_t)); + strcpy(pdn->apn, apn); + + pdn->context = ue; + list_append(&ue->pdn_list, pdn); + + return pdn; +} + +status_t mme_pdn_remove(pdn_t *pdn) +{ + mme_ue_t *ue = NULL; + + d_assert(pdn, return CORE_ERROR, "Null param"); + ue = pdn->context; + d_assert(ue, return CORE_ERROR, "Null param"); + + list_remove(&ue->pdn_list, pdn); + pool_free_node(&mme_pdn_pool, pdn); + + return CORE_OK; +} + +status_t mme_pdn_remove_all(mme_ue_t *ue) +{ + pdn_t *pdn = NULL, *next_pdn = NULL; + + d_assert(ue, return CORE_ERROR, "Null param"); + + pdn = list_first(&ue->pdn_list); + while (pdn) + { + next_pdn = list_next(pdn); + + mme_pdn_remove(pdn); + + pdn = next_pdn; + } + + return CORE_OK; +} + +pdn_t* mme_pdn_find_by_apn(mme_ue_t *ue, c_int8_t *apn) +{ + pdn_t *pdn = NULL; + + d_assert(ue, return NULL, "Null param"); + + pdn = list_first(&ue->pdn_list); + while (pdn) + { + if (strcmp(pdn->apn, apn) == 0) + break; + + pdn = list_next(pdn); + } + + return pdn; +} + +pdn_t* mme_pdn_first(mme_ue_t *ue) +{ + d_assert(ue, return NULL, "Null param"); + return list_first(&ue->pdn_list); +} + +pdn_t* mme_pdn_next(pdn_t *pdn) +{ + return list_next(pdn); +} + diff --git a/src/mme/mme_context.h b/src/mme/mme_context.h index bea774c87..04f4fcbc7 100644 --- a/src/mme/mme_context.h +++ b/src/mme/mme_context.h @@ -71,7 +71,6 @@ typedef struct _mme_context_t { list_t sgw_list; list_t enb_list; - list_t pdn_list; hash_t *mme_ue_s1ap_id_hash; /* hash table for MME-UE-S1AP-ID */ } mme_context_t; @@ -139,15 +138,12 @@ typedef struct _mme_ue_t { /* HSS Info */ c_uint32_t ula_flags; - c_uint32_t max_bandwidth_ul; /* bits per seconds */ c_uint32_t max_bandwidth_dl; /* bits per seconds */ - - pdn_t *pdn[MAX_NUM_OF_PDN]; - int num_of_pdn; - + list_t pdn_list; c_uint32_t subscribed_rau_tau_timer; /* seconds */ + /* ESM Info */ c_uint8_t ebi; /* EPS Bearer ID generator */ list_t esm_list; @@ -200,14 +196,6 @@ CORE_DECLARE(mme_enb_t*) mme_enb_find_by_enb_id(c_uint32_t enb_id); CORE_DECLARE(mme_enb_t*) mme_enb_first(void); CORE_DECLARE(mme_enb_t*) mme_enb_next(mme_enb_t *enb); -CORE_DECLARE(pdn_t*) mme_pdn_add(pdn_id_t id); -CORE_DECLARE(status_t) mme_pdn_remove(pdn_t *pdn); -CORE_DECLARE(status_t) mme_pdn_remove_all(void); -CORE_DECLARE(pdn_t*) mme_pdn_find_by_id(pdn_id_t id); -CORE_DECLARE(pdn_t*) mme_pdn_find_by_apn(c_int8_t *apn); -CORE_DECLARE(pdn_t*) mme_pdn_first(void); -CORE_DECLARE(pdn_t*) mme_pdn_next(pdn_t *pdn); - CORE_DECLARE(mme_ue_t*) mme_ue_add(mme_enb_t *enb); CORE_DECLARE(status_t) mme_ue_remove(mme_ue_t *ue); CORE_DECLARE(status_t) mme_ue_remove_all(); @@ -233,6 +221,13 @@ CORE_DECLARE(mme_esm_t*) mme_esm_find_by_teid(c_uint32_t teid); CORE_DECLARE(mme_esm_t*) mme_esm_first(mme_ue_t *ue); CORE_DECLARE(mme_esm_t*) mme_esm_next(mme_esm_t *esm); +CORE_DECLARE(pdn_t*) mme_pdn_add(mme_ue_t *ue, c_int8_t *apn); +CORE_DECLARE(status_t) mme_pdn_remove(pdn_t *pdn); +CORE_DECLARE(status_t) mme_pdn_remove_all(mme_ue_t *ue); +CORE_DECLARE(pdn_t*) mme_pdn_find_by_apn(mme_ue_t *ue, c_int8_t *apn); +CORE_DECLARE(pdn_t*) mme_pdn_first(mme_ue_t *ue); +CORE_DECLARE(pdn_t*) mme_pdn_next(pdn_t *pdn); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/mme/mme_s11_build.c b/src/mme/mme_s11_build.c index 6e1310c7e..93433635e 100644 --- a/src/mme/mme_s11_build.c +++ b/src/mme/mme_s11_build.c @@ -97,7 +97,6 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_esm_t *esm) req->pdn_type.presence = 1; req->pdn_type.u8 = GTP_PDN_TYPE_IPV4; - memset(&pdn->paa, 0, sizeof(paa_t)); pdn->paa.gtp_type = GTP_PDN_TYPE_IPV4; req->pdn_address_allocation.presence = 1; req->pdn_address_allocation.data = &pdn->paa; diff --git a/src/mme/mme_s6a_handler.c b/src/mme/mme_s6a_handler.c index cb0591e80..f574b9a87 100644 --- a/src/mme/mme_s6a_handler.c +++ b/src/mme/mme_s6a_handler.c @@ -258,7 +258,6 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg) event_t e; mme_ue_t *ue = NULL; pdn_t *pdn = NULL; - c_uint8_t pdn_added = 0; CHECK_SYS_DO(clock_gettime(CLOCK_REALTIME, &ts), return); @@ -326,17 +325,27 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg) case AVP_CODE_ALL_APN_CONFIG_INC_IND: break; case AVP_CODE_APN_CONFIGURATION: + { + c_int8_t apn[MAX_APN_LEN]; + d_assert(fd_avp_search_avp(avpch2, s6a_service_selection, + &avpch3) == 0 && avpch3, error++; goto out,); + d_assert(fd_msg_avp_hdr(avpch3, &hdr) == 0 && hdr, + error++; goto out,); + memcpy(apn, hdr->avp_value->os.data, hdr->avp_value->os.len); + apn[hdr->avp_value->os.len] = 0; + + pdn = mme_pdn_find_by_apn(ue, apn); + if (!pdn) + pdn = mme_pdn_add(ue, apn); + else + d_warn("Duplicate APN:[%s]", apn); + d_assert(pdn, error++; goto out,); + d_assert(fd_avp_search_avp(avpch2, s6a_context_identifier, &avpch3) == 0 && avpch3, error++; goto out,); d_assert(fd_msg_avp_hdr(avpch3, &hdr) == 0 && hdr, error++; goto out,); - pdn = mme_pdn_find_by_id(hdr->avp_value->i32); - if (!pdn) - { - pdn = mme_pdn_add(hdr->avp_value->i32); - pdn_added = 1; - } - d_assert(pdn, error++; goto out,); + pdn->id = hdr->avp_value->i32; d_assert(fd_avp_search_avp(avpch2, s6a_pdn_type, &avpch3) == 0 && avpch3, error++; goto out,); @@ -344,27 +353,6 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg) error++; goto out,); pdn->s6a_type = hdr->avp_value->i32; - d_assert(fd_avp_search_avp(avpch2, s6a_service_selection, - &avpch3) == 0 && avpch3, error++; goto out,); - d_assert(fd_msg_avp_hdr(avpch3, &hdr) == 0 && hdr, - error++; goto out,); - - memcpy(pdn->apn, - hdr->avp_value->os.data, hdr->avp_value->os.len); - pdn->apn[hdr->avp_value->os.len] = 0; - - if (pdn_added) - d_info("PDN(id:%d, type:%s, APN:%s) Added", - pdn->id, - pdn->s6a_type == S6A_PDN_TYPE_IPV4 ? "IPv4" : - pdn->s6a_type == S6A_PDN_TYPE_IPV6 ? "IPv6" : - pdn->s6a_type == S6A_PDN_TYPE_IPV4_AND_IPV6 ? - "IPv4_AND_IPv6" : - pdn->s6a_type == S6A_PDN_TYPE_IPV4_OR_IPV6 ? - "IPv4_OR_IPv6" : - "Unknown Type", - pdn->apn); - d_assert(fd_avp_search_avp(avpch2, s6a_eps_subscribed_qos_profile, &avpch3) == 0 && avpch3, error++; goto out,); @@ -412,6 +400,12 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg) error++; goto out,); pdn->max_bandwidth_dl = hdr->avp_value->i32; break; + } + default: + { + d_warn("Unknown AVP-code:%d", hdr->avp_code); + break; + } } fd_msg_browse(avpch2, MSG_BRW_NEXT, &avpch2, NULL); diff --git a/src/pgw/pgw_context.c b/src/pgw/pgw_context.c index cd840f551..92e88f0ce 100644 --- a/src/pgw/pgw_context.c +++ b/src/pgw/pgw_context.c @@ -10,26 +10,23 @@ static pgw_context_t self; -pool_declare(pgw_pdn_pool, pdn_t, MAX_NUM_OF_PDN); index_declare(pgw_sess_pool, pgw_sess_t, MAX_NUM_OF_UE); +pool_declare(pgw_pdn_pool, pdn_t, MAX_NUM_OF_UE_PDN); static int context_initiaized = 0; status_t pgw_context_init() { - pdn_t *pdn = NULL; - d_assert(context_initiaized == 0, return CORE_ERROR, "MME context already has been initialized"); memset(&self, 0, sizeof(pgw_context_t)); - pool_init(&pgw_pdn_pool, MAX_NUM_OF_PDN); - list_init(&self.pdn_list); - index_init(&pgw_sess_pool, MAX_NUM_OF_UE); list_init(&self.sess_list); + pool_init(&pgw_pdn_pool, MAX_NUM_OF_UE_PDN); + self.s5c_addr = inet_addr("127.0.0.1"); self.s5c_port = GTPV2_C_UDP_PORT + 3; self.s5c_node.addr = inet_addr("127.0.0.1"); @@ -42,17 +39,6 @@ status_t pgw_context_init() self.s5u_node.addr = inet_addr("127.0.0.1"); self.s5u_node.port = GTPV1_U_UDP_PORT; - /*********************************************** - * PDN DB */ - pdn = pgw_pdn_add(); - d_assert(pdn, return -1, "Profile context add failed"); - - pdn->apn[0] = 0x08; - strcpy(pdn->apn+1, "internet"); - - pdn->paa.gtp_type = GTP_PDN_TYPE_IPV4; - pdn->paa.ipv4_addr = inet_addr("45.45.45.113"); /* FIXME */ - context_initiaized = 1; return CORE_OK; @@ -65,7 +51,6 @@ status_t pgw_context_final() gtp_xact_delete_all(&self.s5c_node); pgw_sess_remove_all(); - pgw_pdn_remove_all(); d_print("%d not freed in pgw_sess_pool[%d] in PGW-Context\n", index_size(&pgw_sess_pool) - pool_avail(&pgw_sess_pool), @@ -84,91 +69,6 @@ pgw_context_t* pgw_self() return &self; } -pdn_t* pgw_pdn_add() -{ - pdn_t *pdn = NULL; - - pool_alloc_node(&pgw_pdn_pool, &pdn); - d_assert(pdn, return NULL, "HSS-UE context allocation failed"); - - memset(pdn, 0, sizeof(pdn_t)); - - pdn->id = NEXT_ID(self.pdn_id, 1, 0xffffffff); - - list_append(&self.pdn_list, pdn); - - return pdn; -} - -status_t pgw_pdn_remove(pdn_t *pdn) -{ - d_assert(pdn, return CORE_ERROR, "Null param"); - - list_remove(&self.pdn_list, pdn); - pool_free_node(&pgw_pdn_pool, pdn); - - return CORE_OK; -} - -status_t pgw_pdn_remove_all() -{ - pdn_t *pdn = NULL, *next_pdn = NULL; - - pdn = list_first(&self.pdn_list); - while (pdn) - { - next_pdn = list_next(pdn); - - pgw_pdn_remove(pdn); - - pdn = next_pdn; - } - - return CORE_OK; -} - -pdn_t* pgw_pdn_find_by_id(pdn_id_t id) -{ - pdn_t *pdn = NULL; - - pdn = list_first(&self.pdn_list); - while (pdn) - { - if (pdn->id == id) - break; - - pdn = list_next(pdn); - } - - return pdn; -} - -pdn_t* pgw_pdn_find_by_apn(c_int8_t *apn) -{ - pdn_t *pdn = NULL; - - pdn = list_first(&self.pdn_list); - while (pdn) - { - if (strcmp(pdn->apn, apn) == 0) - break; - - pdn = list_next(pdn); - } - - return pdn; -} - -pdn_t* pgw_pdn_first() -{ - return list_first(&self.pdn_list); -} - -pdn_t* pgw_pdn_next(pdn_t *pdn) -{ - return list_next(pdn); -} - pgw_sess_t *pgw_sess_add() { pgw_sess_t *sess = NULL; @@ -178,6 +78,7 @@ pgw_sess_t *pgw_sess_add() sess->teid = sess->index; /* derived from an index */ + list_init(&sess->pdn_list); list_append(&self.sess_list, sess); return sess; @@ -187,6 +88,8 @@ status_t pgw_sess_remove(pgw_sess_t *sess) { d_assert(sess, return CORE_ERROR, "Null param"); + pgw_pdn_remove_all(sess); + list_remove(&self.sess_list, sess); index_free(&pgw_sess_pool, sess); @@ -230,3 +133,85 @@ pgw_sess_t* pgw_sess_next(pgw_sess_t *enb) { return list_next(enb); } + +pdn_t* pgw_pdn_add(pgw_sess_t *sess, c_int8_t *apn) +{ + pdn_t *pdn = NULL; + + d_assert(sess, return NULL, "Null param"); + d_assert(apn, return NULL, "Null param"); + + pool_alloc_node(&pgw_pdn_pool, &pdn); + d_assert(pdn, return NULL, "PDN context allocation failed"); + + memset(pdn, 0, sizeof(pdn_t)); + strcpy(pdn->apn, apn); + + pdn->context = sess; + list_append(&sess->pdn_list, pdn); + + return pdn; +} + +status_t pgw_pdn_remove(pdn_t *pdn) +{ + pgw_sess_t *sess = NULL; + + d_assert(pdn, return CORE_ERROR, "Null param"); + sess = pdn->context; + d_assert(sess, return CORE_ERROR, "Null param"); + + list_remove(&sess->pdn_list, pdn); + pool_free_node(&pgw_pdn_pool, pdn); + + return CORE_OK; +} + +status_t pgw_pdn_remove_all(pgw_sess_t *sess) +{ + pdn_t *pdn = NULL, *next_pdn = NULL; + + d_assert(sess, return CORE_ERROR, "Null param"); + + pdn = list_first(&sess->pdn_list); + while (pdn) + { + next_pdn = list_next(pdn); + + pgw_pdn_remove(pdn); + + pdn = next_pdn; + } + + return CORE_OK; +} + +pdn_t* pgw_pdn_find_by_apn(pgw_sess_t *sess, c_int8_t *apn) +{ + pdn_t *pdn = NULL; + + d_assert(sess, return NULL, "Null param"); + + pdn = list_first(&sess->pdn_list); + while (pdn) + { + if (strcmp(pdn->apn, apn) == 0) + break; + + pdn = list_next(pdn); + } + + return pdn; +} + +pdn_t* pgw_pdn_first(pgw_sess_t *sess) +{ + d_assert(sess, return NULL, "Null param"); + return list_first(&sess->pdn_list); +} + +pdn_t* pgw_pdn_next(pdn_t *pdn) +{ + return list_next(pdn); +} + diff --git a/src/pgw/pgw_context.h b/src/pgw/pgw_context.h index 0a27bfba3..b65d4df4b 100644 --- a/src/pgw/pgw_context.h +++ b/src/pgw/pgw_context.h @@ -26,13 +26,10 @@ typedef struct _pgw_context_t { net_sock_t* s5u_sock; /* PGW S5-U local listen socket */ gtp_node_t s5u_node; /* PGW S5-U remote GTPv1-U node */ - msgq_id queue_id; /* Queue for processing PGW control plane */ + msgq_id queue_id; /* Qsesssess for processing PGW control plane */ tm_service_t tm_service; /* Timer Service */ gtp_xact_ctx_t gtp_xact_ctx; /* GTP Transaction Context */ - c_uint32_t pdn_id; /* PDN ID Generator */ - list_t pdn_list; - list_t sess_list; } pgw_context_t; @@ -46,6 +43,8 @@ typedef struct _pgw_sess_t { c_uint32_t sgw_addr; /* SGW-S5C-F-TEID IPv4 Address */ c_uint32_t sgw_teid; /* SGW-S5C-F-TEID */ + + list_t pdn_list; } pgw_sess_t; CORE_DECLARE(status_t) pgw_context_init(void); @@ -61,12 +60,11 @@ CORE_DECLARE(pgw_sess_t*) pgw_sess_find_by_teid(c_uint32_t teid); CORE_DECLARE(pgw_sess_t *) pgw_sess_first(); CORE_DECLARE(pgw_sess_t *) pgw_sess_next(pgw_sess_t *sess); -CORE_DECLARE(pdn_t*) pgw_pdn_add(); +CORE_DECLARE(pdn_t*) pgw_pdn_add(pgw_sess_t *sess, c_int8_t *apn); CORE_DECLARE(status_t) pgw_pdn_remove(pdn_t *pdn); -CORE_DECLARE(status_t) pgw_pdn_remove_all(void); -CORE_DECLARE(pdn_t*) pgw_pdn_find_by_id(pdn_id_t id); -CORE_DECLARE(pdn_t*) pgw_pdn_find_by_apn(c_int8_t *apn); -CORE_DECLARE(pdn_t*) pgw_pdn_first(void); +CORE_DECLARE(status_t) pgw_pdn_remove_all(pgw_sess_t *sess); +CORE_DECLARE(pdn_t*) pgw_pdn_find_by_apn(pgw_sess_t *sess, c_int8_t *apn); +CORE_DECLARE(pdn_t*) pgw_pdn_first(pgw_sess_t *sess); CORE_DECLARE(pdn_t*) pgw_pdn_next(pdn_t *pdn); #ifdef __cplusplus diff --git a/src/pgw/pgw_handler.c b/src/pgw/pgw_handler.c index 5baf3e8c0..898cc660d 100644 --- a/src/pgw/pgw_handler.c +++ b/src/pgw/pgw_handler.c @@ -41,15 +41,6 @@ void pgw_handle_create_session_request( return; } - memcpy(apn, req->access_point_name.data, req->access_point_name.len); - apn[req->access_point_name.len] = 0; - pdn = pgw_pdn_find_by_apn(apn); - if (!pdn) - { - d_error("No PDN Context-APN[%s]", apn); - return; - } - sgw_f_teid = req->sender_f_teid_for_control_plane.data; if (!(sgw_f_teid->ipv4 == 1 && sgw_f_teid->ipv6 == 0 && sgw_f_teid->interface_type == GTP_F_TEID_S5_S8_SGW_GTP_C)) @@ -61,11 +52,20 @@ void pgw_handle_create_session_request( } sess = pgw_sess_add(); - d_assert(sess, return, "sess_add failed"); + d_assert(sess, return, "No Session Context"); sess->sgw_teid = ntohl(sgw_f_teid->teid); sess->sgw_addr = sgw_f_teid->ipv4_addr; + memcpy(apn, req->access_point_name.data, req->access_point_name.len); + apn[req->access_point_name.len] = 0; + pdn = pgw_pdn_find_by_apn(sess, apn); + if (!pdn) + { + pdn = pgw_pdn_add(sess, apn); + } + d_assert(pdn, pgw_sess_remove(sess); return, "No PDN Context"); + memset(>p_message, 0, sizeof(gtp_message_t)); memset(&cause, 0, sizeof(cause)); @@ -86,6 +86,9 @@ void pgw_handle_create_session_request( rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface. len = GTP_F_TEID_IPV4_LEN; + pdn->paa.gtp_type = GTP_PDN_TYPE_IPV4; + pdn->paa.ipv4_addr = inet_addr("45.45.45.113"); /* FIXME */ + rsp->pdn_address_allocation.presence = 1; rsp->pdn_address_allocation.data = &pdn->paa; rsp->pdn_address_allocation.len = PAA_IPV4_LEN;