forked from acouzens/open5gs
update it
This commit is contained in:
parent
258cc29454
commit
fbeada07a1
|
@ -7,12 +7,13 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#define MAX_NUM_OF_PDN 4
|
|
||||||
|
|
||||||
#define MAX_UE_PER_ENB 128
|
#define MAX_UE_PER_ENB 128
|
||||||
#define MAX_NUM_OF_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_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 IPV6_LEN 16
|
||||||
|
|
||||||
#define MAX_SDU_LEN 2048
|
#define MAX_SDU_LEN 2048
|
||||||
|
@ -92,11 +93,10 @@ ED2(c_uint8_t spare:6;,
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
* PDN Structure */
|
* PDN Structure */
|
||||||
typedef c_uint32_t pdn_id_t;
|
|
||||||
typedef struct _pdn_t {
|
typedef struct _pdn_t {
|
||||||
lnode_t node; /**< A node of list_t */
|
lnode_t node; /**< A node of list_t */
|
||||||
|
|
||||||
pdn_id_t id;
|
c_uint32_t id;
|
||||||
c_int8_t apn[MAX_APN_LEN];
|
c_int8_t apn[MAX_APN_LEN];
|
||||||
#define S6A_PDN_TYPE_IPV4 0
|
#define S6A_PDN_TYPE_IPV4 0
|
||||||
#define S6A_PDN_TYPE_IPV6 1
|
#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_ENABLED 0
|
||||||
#define PDN_PRE_EMPTION_VULNERABILITY_DISABLED 1
|
#define PDN_PRE_EMPTION_VULNERABILITY_DISABLED 1
|
||||||
c_uint8_t pre_emption_vulnerability;
|
c_uint8_t pre_emption_vulnerability;
|
||||||
|
|
||||||
|
void *context;
|
||||||
} pdn_t;
|
} pdn_t;
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
|
|
|
@ -27,6 +27,7 @@ status_t hss_context_init(void)
|
||||||
hss_profile_t *profile;
|
hss_profile_t *profile;
|
||||||
pdn_t *pdn;
|
pdn_t *pdn;
|
||||||
hss_ue_t *ue;
|
hss_ue_t *ue;
|
||||||
|
c_int8_t apn[MAX_APN_LEN];
|
||||||
|
|
||||||
memset(&self, 0, sizeof(hss_context_t));
|
memset(&self, 0, sizeof(hss_context_t));
|
||||||
|
|
||||||
|
@ -62,11 +63,11 @@ status_t hss_context_init(void)
|
||||||
|
|
||||||
/***********************************************
|
/***********************************************
|
||||||
* PDN DB */
|
* PDN DB */
|
||||||
pdn = hss_pdn_add();
|
apn[0] = 0x08;
|
||||||
d_assert(pdn, return -1, "Profile context add failed");
|
strcpy(apn+1, "internet");
|
||||||
|
|
||||||
pdn->apn[0] = 0x08;
|
pdn = hss_pdn_add(apn);
|
||||||
strcpy(pdn->apn+1, "internet");
|
d_assert(pdn, return -1, "PDN context add failed");
|
||||||
|
|
||||||
pdn->s6a_type = S6A_PDN_TYPE_IPV4;
|
pdn->s6a_type = S6A_PDN_TYPE_IPV4;
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ void hss_context_final(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdn_t* hss_pdn_add()
|
pdn_t* hss_pdn_add(c_int8_t *apn)
|
||||||
{
|
{
|
||||||
pdn_t *pdn = NULL;
|
pdn_t *pdn = NULL;
|
||||||
|
|
||||||
|
@ -130,6 +131,7 @@ pdn_t* hss_pdn_add()
|
||||||
|
|
||||||
memset(pdn, 0, sizeof(pdn_t));
|
memset(pdn, 0, sizeof(pdn_t));
|
||||||
|
|
||||||
|
strcpy(pdn->apn, apn);
|
||||||
pdn->id = NEXT_ID(self.pdn_id, 1, 0xffffffff);
|
pdn->id = NEXT_ID(self.pdn_id, 1, 0xffffffff);
|
||||||
|
|
||||||
list_append(&self.pdn_list, pdn);
|
list_append(&self.pdn_list, pdn);
|
||||||
|
@ -164,14 +166,14 @@ status_t hss_pdn_remove_all()
|
||||||
return CORE_OK;
|
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_t *pdn = NULL;
|
||||||
|
|
||||||
pdn = list_first(&self.pdn_list);
|
pdn = list_first(&self.pdn_list);
|
||||||
while (pdn)
|
while (pdn)
|
||||||
{
|
{
|
||||||
if (pdn->id == id)
|
if (strcmp(pdn->apn, apn) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pdn = list_next(pdn);
|
pdn = list_next(pdn);
|
||||||
|
|
|
@ -95,10 +95,10 @@ CORE_DECLARE(status_t) hss_context_init(void);
|
||||||
CORE_DECLARE(void) hss_context_final(void);
|
CORE_DECLARE(void) hss_context_final(void);
|
||||||
CORE_DECLARE(hss_context_t*) hss_self(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(pdn_t *pdn);
|
||||||
CORE_DECLARE(status_t) hss_pdn_remove_all(void);
|
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_first(void);
|
||||||
CORE_DECLARE(pdn_t*) hss_pdn_next(pdn_t *pdn);
|
CORE_DECLARE(pdn_t*) hss_pdn_next(pdn_t *pdn);
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,18 @@ void esm_handle_pdn_connectivity_request(mme_esm_t *esm,
|
||||||
void esm_handle_information_response(mme_esm_t *esm,
|
void esm_handle_information_response(mme_esm_t *esm,
|
||||||
nas_esm_information_response_t *esm_information_response)
|
nas_esm_information_response_t *esm_information_response)
|
||||||
{
|
{
|
||||||
|
mme_ue_t *ue = NULL;
|
||||||
pkbuf_t *pkbuf = NULL;
|
pkbuf_t *pkbuf = NULL;
|
||||||
status_t rv;
|
status_t rv;
|
||||||
|
|
||||||
|
d_assert(esm, return, "Null param");
|
||||||
|
ue = esm->ue;
|
||||||
|
d_assert(ue, return, "Null param");
|
||||||
|
|
||||||
if (esm_information_response->presencemask &
|
if (esm_information_response->presencemask &
|
||||||
NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT)
|
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);
|
esm_information_response->access_point_name.apn);
|
||||||
d_assert(esm->pdn, return, "No PDN Context[APN:%s])",
|
d_assert(esm->pdn, return, "No PDN Context[APN:%s])",
|
||||||
esm_information_response->access_point_name.apn);
|
esm_information_response->access_point_name.apn);
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#define MAX_NUM_OF_SGW 8
|
#define MAX_NUM_OF_SGW 8
|
||||||
#define MAX_NUM_OF_ESM (MAX_NUM_OF_UE * MAX_ESM_PER_UE)
|
#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 S1AP_SCTP_PORT 36412
|
||||||
|
|
||||||
#define MIN_EPS_BEARER_ID 5
|
#define MIN_EPS_BEARER_ID 5
|
||||||
|
@ -22,11 +24,11 @@
|
||||||
static mme_context_t self;
|
static mme_context_t self;
|
||||||
|
|
||||||
pool_declare(mme_sgw_pool, mme_sgw_t, MAX_NUM_OF_SGW);
|
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_enb_pool, mme_enb_t, MAX_NUM_OF_ENB);
|
||||||
index_declare(mme_ue_pool, mme_ue_t, MAX_NUM_OF_UE);
|
index_declare(mme_ue_pool, mme_ue_t, MAX_NUM_OF_UE);
|
||||||
index_declare(mme_esm_pool, mme_esm_t, MAX_NUM_OF_ESM);
|
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;
|
static int context_initialized = 0;
|
||||||
|
|
||||||
|
@ -41,14 +43,12 @@ status_t mme_context_init()
|
||||||
pool_init(&mme_sgw_pool, MAX_NUM_OF_SGW);
|
pool_init(&mme_sgw_pool, MAX_NUM_OF_SGW);
|
||||||
list_init(&self.sgw_list);
|
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);
|
index_init(&mme_enb_pool, MAX_NUM_OF_ENB);
|
||||||
list_init(&self.enb_list);
|
list_init(&self.enb_list);
|
||||||
|
|
||||||
index_init(&mme_ue_pool, MAX_NUM_OF_UE);
|
index_init(&mme_ue_pool, MAX_NUM_OF_UE);
|
||||||
index_init(&mme_esm_pool, MAX_NUM_OF_ESM);
|
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();
|
self.mme_ue_s1ap_id_hash = hash_make();
|
||||||
|
|
||||||
|
@ -94,17 +94,16 @@ status_t mme_context_final()
|
||||||
|
|
||||||
mme_sgw_remove_all();
|
mme_sgw_remove_all();
|
||||||
mme_enb_remove_all();
|
mme_enb_remove_all();
|
||||||
mme_pdn_remove_all();
|
|
||||||
|
|
||||||
d_assert(self.mme_ue_s1ap_id_hash, , "Null param");
|
d_assert(self.mme_ue_s1ap_id_hash, , "Null param");
|
||||||
hash_destroy(self.mme_ue_s1ap_id_hash);
|
hash_destroy(self.mme_ue_s1ap_id_hash);
|
||||||
|
|
||||||
|
pool_final(&mme_pdn_pool);
|
||||||
index_final(&mme_esm_pool);
|
index_final(&mme_esm_pool);
|
||||||
index_final(&mme_ue_pool);
|
index_final(&mme_ue_pool);
|
||||||
index_final(&mme_enb_pool);
|
|
||||||
|
|
||||||
|
index_final(&mme_enb_pool);
|
||||||
pool_final(&mme_sgw_pool);
|
pool_final(&mme_sgw_pool);
|
||||||
pool_final(&mme_pdn_pool);
|
|
||||||
|
|
||||||
context_initialized = 0;
|
context_initialized = 0;
|
||||||
|
|
||||||
|
@ -292,91 +291,6 @@ mme_enb_t* mme_enb_next(mme_enb_t *enb)
|
||||||
return list_next(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* mme_ue_add(mme_enb_t *enb)
|
||||||
{
|
{
|
||||||
mme_ue_t *ue = NULL;
|
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,
|
hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id,
|
||||||
sizeof(ue->mme_ue_s1ap_id), ue);
|
sizeof(ue->mme_ue_s1ap_id), ue);
|
||||||
|
|
||||||
|
list_init(&ue->pdn_list);
|
||||||
ue->ebi = MIN_EPS_BEARER_ID - 1;
|
ue->ebi = MIN_EPS_BEARER_ID - 1;
|
||||||
|
|
||||||
ue->enb = enb;
|
|
||||||
list_init(&ue->esm_list);
|
list_init(&ue->esm_list);
|
||||||
list_append(&enb->ue_list, ue);
|
list_append(&enb->ue_list, ue);
|
||||||
|
|
||||||
|
ue->enb = enb;
|
||||||
|
|
||||||
fsm_create(&ue->sm, emm_state_initial, emm_state_final);
|
fsm_create(&ue->sm, emm_state_initial, emm_state_final);
|
||||||
fsm_init(&ue->sm, 0);
|
fsm_init(&ue->sm, 0);
|
||||||
|
|
||||||
|
@ -413,6 +329,7 @@ status_t mme_ue_remove(mme_ue_t *ue)
|
||||||
fsm_clear(&ue->sm);
|
fsm_clear(&ue->sm);
|
||||||
|
|
||||||
mme_esm_remove_all(ue);
|
mme_esm_remove_all(ue);
|
||||||
|
mme_pdn_remove_all(ue);
|
||||||
|
|
||||||
list_remove(&ue->enb->ue_list, ue);
|
list_remove(&ue->enb->ue_list, ue);
|
||||||
hash_set(self.mme_ue_s1ap_id_hash, &ue->mme_ue_s1ap_id,
|
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);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,6 @@ typedef struct _mme_context_t {
|
||||||
|
|
||||||
list_t sgw_list;
|
list_t sgw_list;
|
||||||
list_t enb_list;
|
list_t enb_list;
|
||||||
list_t pdn_list;
|
|
||||||
|
|
||||||
hash_t *mme_ue_s1ap_id_hash; /* hash table for MME-UE-S1AP-ID */
|
hash_t *mme_ue_s1ap_id_hash; /* hash table for MME-UE-S1AP-ID */
|
||||||
} mme_context_t;
|
} mme_context_t;
|
||||||
|
@ -139,15 +138,12 @@ typedef struct _mme_ue_t {
|
||||||
|
|
||||||
/* HSS Info */
|
/* HSS Info */
|
||||||
c_uint32_t ula_flags;
|
c_uint32_t ula_flags;
|
||||||
|
|
||||||
c_uint32_t max_bandwidth_ul; /* bits per seconds */
|
c_uint32_t max_bandwidth_ul; /* bits per seconds */
|
||||||
c_uint32_t max_bandwidth_dl; /* bits per seconds */
|
c_uint32_t max_bandwidth_dl; /* bits per seconds */
|
||||||
|
list_t pdn_list;
|
||||||
pdn_t *pdn[MAX_NUM_OF_PDN];
|
|
||||||
int num_of_pdn;
|
|
||||||
|
|
||||||
c_uint32_t subscribed_rau_tau_timer; /* seconds */
|
c_uint32_t subscribed_rau_tau_timer; /* seconds */
|
||||||
|
|
||||||
|
/* ESM Info */
|
||||||
c_uint8_t ebi; /* EPS Bearer ID generator */
|
c_uint8_t ebi; /* EPS Bearer ID generator */
|
||||||
list_t esm_list;
|
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_first(void);
|
||||||
CORE_DECLARE(mme_enb_t*) mme_enb_next(mme_enb_t *enb);
|
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(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(mme_ue_t *ue);
|
||||||
CORE_DECLARE(status_t) mme_ue_remove_all();
|
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_first(mme_ue_t *ue);
|
||||||
CORE_DECLARE(mme_esm_t*) mme_esm_next(mme_esm_t *esm);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
|
@ -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.presence = 1;
|
||||||
req->pdn_type.u8 = GTP_PDN_TYPE_IPV4;
|
req->pdn_type.u8 = GTP_PDN_TYPE_IPV4;
|
||||||
|
|
||||||
memset(&pdn->paa, 0, sizeof(paa_t));
|
|
||||||
pdn->paa.gtp_type = GTP_PDN_TYPE_IPV4;
|
pdn->paa.gtp_type = GTP_PDN_TYPE_IPV4;
|
||||||
req->pdn_address_allocation.presence = 1;
|
req->pdn_address_allocation.presence = 1;
|
||||||
req->pdn_address_allocation.data = &pdn->paa;
|
req->pdn_address_allocation.data = &pdn->paa;
|
||||||
|
|
|
@ -258,7 +258,6 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
||||||
event_t e;
|
event_t e;
|
||||||
mme_ue_t *ue = NULL;
|
mme_ue_t *ue = NULL;
|
||||||
pdn_t *pdn = NULL;
|
pdn_t *pdn = NULL;
|
||||||
c_uint8_t pdn_added = 0;
|
|
||||||
|
|
||||||
CHECK_SYS_DO(clock_gettime(CLOCK_REALTIME, &ts), return);
|
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:
|
case AVP_CODE_ALL_APN_CONFIG_INC_IND:
|
||||||
break;
|
break;
|
||||||
case AVP_CODE_APN_CONFIGURATION:
|
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,
|
d_assert(fd_avp_search_avp(avpch2, s6a_context_identifier,
|
||||||
&avpch3) == 0 && avpch3, error++; goto out,);
|
&avpch3) == 0 && avpch3, error++; goto out,);
|
||||||
d_assert(fd_msg_avp_hdr(avpch3, &hdr) == 0 && hdr,
|
d_assert(fd_msg_avp_hdr(avpch3, &hdr) == 0 && hdr,
|
||||||
error++; goto out,);
|
error++; goto out,);
|
||||||
pdn = mme_pdn_find_by_id(hdr->avp_value->i32);
|
pdn->id = hdr->avp_value->i32;
|
||||||
if (!pdn)
|
|
||||||
{
|
|
||||||
pdn = mme_pdn_add(hdr->avp_value->i32);
|
|
||||||
pdn_added = 1;
|
|
||||||
}
|
|
||||||
d_assert(pdn, error++; goto out,);
|
|
||||||
|
|
||||||
d_assert(fd_avp_search_avp(avpch2, s6a_pdn_type,
|
d_assert(fd_avp_search_avp(avpch2, s6a_pdn_type,
|
||||||
&avpch3) == 0 && avpch3, error++; goto out,);
|
&avpch3) == 0 && avpch3, error++; goto out,);
|
||||||
|
@ -344,27 +353,6 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
||||||
error++; goto out,);
|
error++; goto out,);
|
||||||
pdn->s6a_type = hdr->avp_value->i32;
|
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,
|
d_assert(fd_avp_search_avp(avpch2,
|
||||||
s6a_eps_subscribed_qos_profile, &avpch3) == 0 &&
|
s6a_eps_subscribed_qos_profile, &avpch3) == 0 &&
|
||||||
avpch3, error++; goto out,);
|
avpch3, error++; goto out,);
|
||||||
|
@ -412,6 +400,12 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
||||||
error++; goto out,);
|
error++; goto out,);
|
||||||
pdn->max_bandwidth_dl = hdr->avp_value->i32;
|
pdn->max_bandwidth_dl = hdr->avp_value->i32;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
d_warn("Unknown AVP-code:%d", hdr->avp_code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_msg_browse(avpch2, MSG_BRW_NEXT, &avpch2, NULL);
|
fd_msg_browse(avpch2, MSG_BRW_NEXT, &avpch2, NULL);
|
||||||
|
|
|
@ -10,26 +10,23 @@
|
||||||
|
|
||||||
static pgw_context_t self;
|
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);
|
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;
|
static int context_initiaized = 0;
|
||||||
|
|
||||||
status_t pgw_context_init()
|
status_t pgw_context_init()
|
||||||
{
|
{
|
||||||
pdn_t *pdn = NULL;
|
|
||||||
|
|
||||||
d_assert(context_initiaized == 0, return CORE_ERROR,
|
d_assert(context_initiaized == 0, return CORE_ERROR,
|
||||||
"MME context already has been initialized");
|
"MME context already has been initialized");
|
||||||
|
|
||||||
memset(&self, 0, sizeof(pgw_context_t));
|
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);
|
index_init(&pgw_sess_pool, MAX_NUM_OF_UE);
|
||||||
list_init(&self.sess_list);
|
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_addr = inet_addr("127.0.0.1");
|
||||||
self.s5c_port = GTPV2_C_UDP_PORT + 3;
|
self.s5c_port = GTPV2_C_UDP_PORT + 3;
|
||||||
self.s5c_node.addr = inet_addr("127.0.0.1");
|
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.addr = inet_addr("127.0.0.1");
|
||||||
self.s5u_node.port = GTPV1_U_UDP_PORT;
|
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;
|
context_initiaized = 1;
|
||||||
|
|
||||||
return CORE_OK;
|
return CORE_OK;
|
||||||
|
@ -65,7 +51,6 @@ status_t pgw_context_final()
|
||||||
|
|
||||||
gtp_xact_delete_all(&self.s5c_node);
|
gtp_xact_delete_all(&self.s5c_node);
|
||||||
pgw_sess_remove_all();
|
pgw_sess_remove_all();
|
||||||
pgw_pdn_remove_all();
|
|
||||||
|
|
||||||
d_print("%d not freed in pgw_sess_pool[%d] in PGW-Context\n",
|
d_print("%d not freed in pgw_sess_pool[%d] in PGW-Context\n",
|
||||||
index_size(&pgw_sess_pool) - pool_avail(&pgw_sess_pool),
|
index_size(&pgw_sess_pool) - pool_avail(&pgw_sess_pool),
|
||||||
|
@ -84,91 +69,6 @@ pgw_context_t* pgw_self()
|
||||||
return &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 *pgw_sess_add()
|
||||||
{
|
{
|
||||||
pgw_sess_t *sess = NULL;
|
pgw_sess_t *sess = NULL;
|
||||||
|
@ -178,6 +78,7 @@ pgw_sess_t *pgw_sess_add()
|
||||||
|
|
||||||
sess->teid = sess->index; /* derived from an index */
|
sess->teid = sess->index; /* derived from an index */
|
||||||
|
|
||||||
|
list_init(&sess->pdn_list);
|
||||||
list_append(&self.sess_list, sess);
|
list_append(&self.sess_list, sess);
|
||||||
|
|
||||||
return sess;
|
return sess;
|
||||||
|
@ -187,6 +88,8 @@ status_t pgw_sess_remove(pgw_sess_t *sess)
|
||||||
{
|
{
|
||||||
d_assert(sess, return CORE_ERROR, "Null param");
|
d_assert(sess, return CORE_ERROR, "Null param");
|
||||||
|
|
||||||
|
pgw_pdn_remove_all(sess);
|
||||||
|
|
||||||
list_remove(&self.sess_list, sess);
|
list_remove(&self.sess_list, sess);
|
||||||
index_free(&pgw_sess_pool, 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);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,10 @@ typedef struct _pgw_context_t {
|
||||||
net_sock_t* s5u_sock; /* PGW S5-U local listen socket */
|
net_sock_t* s5u_sock; /* PGW S5-U local listen socket */
|
||||||
gtp_node_t s5u_node; /* PGW S5-U remote GTPv1-U node */
|
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 */
|
tm_service_t tm_service; /* Timer Service */
|
||||||
gtp_xact_ctx_t gtp_xact_ctx; /* GTP Transaction Context */
|
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;
|
list_t sess_list;
|
||||||
} pgw_context_t;
|
} 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_addr; /* SGW-S5C-F-TEID IPv4 Address */
|
||||||
c_uint32_t sgw_teid; /* SGW-S5C-F-TEID */
|
c_uint32_t sgw_teid; /* SGW-S5C-F-TEID */
|
||||||
|
|
||||||
|
list_t pdn_list;
|
||||||
} pgw_sess_t;
|
} pgw_sess_t;
|
||||||
|
|
||||||
CORE_DECLARE(status_t) pgw_context_init(void);
|
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_first();
|
||||||
CORE_DECLARE(pgw_sess_t *) pgw_sess_next(pgw_sess_t *sess);
|
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(pdn_t *pdn);
|
||||||
CORE_DECLARE(status_t) pgw_pdn_remove_all(void);
|
CORE_DECLARE(status_t) pgw_pdn_remove_all(pgw_sess_t *sess);
|
||||||
CORE_DECLARE(pdn_t*) pgw_pdn_find_by_id(pdn_id_t id);
|
CORE_DECLARE(pdn_t*) pgw_pdn_find_by_apn(pgw_sess_t *sess, c_int8_t *apn);
|
||||||
CORE_DECLARE(pdn_t*) pgw_pdn_find_by_apn(c_int8_t *apn);
|
CORE_DECLARE(pdn_t*) pgw_pdn_first(pgw_sess_t *sess);
|
||||||
CORE_DECLARE(pdn_t*) pgw_pdn_first(void);
|
|
||||||
CORE_DECLARE(pdn_t*) pgw_pdn_next(pdn_t *pdn);
|
CORE_DECLARE(pdn_t*) pgw_pdn_next(pdn_t *pdn);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -41,15 +41,6 @@ void pgw_handle_create_session_request(
|
||||||
return;
|
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;
|
sgw_f_teid = req->sender_f_teid_for_control_plane.data;
|
||||||
if (!(sgw_f_teid->ipv4 == 1 && sgw_f_teid->ipv6 == 0 &&
|
if (!(sgw_f_teid->ipv4 == 1 && sgw_f_teid->ipv6 == 0 &&
|
||||||
sgw_f_teid->interface_type == GTP_F_TEID_S5_S8_SGW_GTP_C))
|
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();
|
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_teid = ntohl(sgw_f_teid->teid);
|
||||||
sess->sgw_addr = sgw_f_teid->ipv4_addr;
|
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(>p_message, 0, sizeof(gtp_message_t));
|
||||||
|
|
||||||
memset(&cause, 0, sizeof(cause));
|
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.
|
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;
|
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.presence = 1;
|
||||||
rsp->pdn_address_allocation.data = &pdn->paa;
|
rsp->pdn_address_allocation.data = &pdn->paa;
|
||||||
rsp->pdn_address_allocation.len = PAA_IPV4_LEN;
|
rsp->pdn_address_allocation.len = PAA_IPV4_LEN;
|
||||||
|
|
Loading…
Reference in New Issue