Now, F-TEID is allocated in the UP function.

This commit is contained in:
Sukchan Lee 2020-10-25 22:43:53 -04:00
parent aa81bb2c89
commit a470131489
28 changed files with 922 additions and 237 deletions

View File

@ -341,6 +341,29 @@ void ogs_pfcp_build_create_pdr(
}
}
void ogs_pfcp_build_created_pdr(
ogs_pfcp_tlv_created_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr)
{
ogs_assert(message);
ogs_assert(pdr);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = pdr->id;
if (ogs_pfcp_self()->up_function_features.ftup) {
if (pdr->f_teid_len) {
memcpy(&pdrbuf[i].f_teid, &pdr->f_teid, pdr->f_teid_len);
pdrbuf[i].f_teid.teid = htobe32(pdr->f_teid.teid);
message->local_f_teid.presence = 1;
message->local_f_teid.data = &pdrbuf[i].f_teid;
message->local_f_teid.len = pdr->f_teid_len;
}
}
}
void ogs_pfcp_build_update_pdr(
ogs_pfcp_tlv_update_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr)
{

View File

@ -40,6 +40,8 @@ void ogs_pfcp_pdrbuf_clear(void);
void ogs_pfcp_build_create_pdr(
ogs_pfcp_tlv_create_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr);
void ogs_pfcp_build_created_pdr(
ogs_pfcp_tlv_created_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr);
void ogs_pfcp_build_update_pdr(
ogs_pfcp_tlv_update_pdr_t *message, int i, ogs_pfcp_pdr_t *pdr);

View File

@ -835,11 +835,15 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess)
ogs_assert(pdr);
memset(pdr, 0, sizeof *pdr);
pdr->index = ogs_pool_index(&ogs_pfcp_pdr_pool, pdr);
ogs_assert(pdr->index > 0 &&
pdr->index <= ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR);
ogs_pool_alloc(&sess->pdr_id_pool, &pdr->id_node);
ogs_assert(pdr->id_node);
pdr->index = *(pdr->id_node);
ogs_assert(pdr->index > 0 && pdr->index <= OGS_MAX_NUM_OF_PDR);
pdr->id = *(pdr->id_node);
ogs_assert(pdr->id > 0 && pdr->id <= OGS_MAX_NUM_OF_PDR);
pdr->sess = sess;
ogs_list_add(&sess->pdr_list, pdr);
@ -983,8 +987,8 @@ ogs_pfcp_far_t *ogs_pfcp_far_add(ogs_pfcp_sess_t *sess)
ogs_pool_alloc(&sess->far_id_pool, &far->id_node);
ogs_assert(far->id_node);
far->index = *(far->id_node);
ogs_assert(far->index > 0 && far->index <= OGS_MAX_NUM_OF_FAR);
far->id = *(far->id_node);
ogs_assert(far->id > 0 && far->id <= OGS_MAX_NUM_OF_FAR);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
@ -1172,8 +1176,8 @@ ogs_pfcp_urr_t *ogs_pfcp_urr_add(ogs_pfcp_sess_t *sess)
ogs_pool_alloc(&sess->urr_id_pool, &urr->id_node);
ogs_assert(urr->id_node);
urr->index = *(urr->id_node);
ogs_assert(urr->index > 0 && urr->index <= OGS_MAX_NUM_OF_URR);
urr->id = *(urr->id_node);
ogs_assert(urr->id > 0 && urr->id <= OGS_MAX_NUM_OF_URR);
urr->sess = sess;
ogs_list_add(&sess->urr_list, urr);
@ -1250,8 +1254,8 @@ ogs_pfcp_qer_t *ogs_pfcp_qer_add(ogs_pfcp_sess_t *sess)
ogs_pool_alloc(&sess->qer_id_pool, &qer->id_node);
ogs_assert(qer->id_node);
qer->index = *(qer->id_node);
ogs_assert(qer->index > 0 && qer->index <= OGS_MAX_NUM_OF_QER);
qer->id = *(qer->id_node);
ogs_assert(qer->id > 0 && qer->id <= OGS_MAX_NUM_OF_QER);
qer->sess = sess;
ogs_list_add(&sess->qer_list, qer);

View File

@ -99,6 +99,9 @@ typedef struct ogs_pfcp_node_s {
uint8_t rr_enable;
ogs_list_t gtpu_resource_list; /* User Plane IP Resource Information */
ogs_pfcp_up_function_features_t up_function_features;
int up_function_features_len;
} ogs_pfcp_node_t;
typedef struct ogs_pfcp_gtpu_resource_s {
@ -160,7 +163,6 @@ typedef struct ogs_pfcp_far_hashkey_s {
typedef struct ogs_pfcp_far_s {
ogs_lnode_t lnode;
uint32_t index;
int hashkey_len;
ogs_pfcp_far_hashkey_t hashkey;
@ -184,7 +186,6 @@ typedef struct ogs_pfcp_far_s {
typedef struct ogs_pfcp_urr_s {
ogs_lnode_t lnode;
uint32_t index;
uint8_t *id_node; /* Pool-Node for ID */
ogs_pfcp_urr_id_t id;
@ -194,7 +195,6 @@ typedef struct ogs_pfcp_urr_s {
typedef struct ogs_pfcp_qer_s {
ogs_lnode_t lnode;
uint32_t index;
uint8_t *id_node; /* Pool-Node for ID */
ogs_pfcp_qer_id_t id;
@ -210,7 +210,6 @@ typedef struct ogs_pfcp_qer_s {
typedef struct ogs_pfcp_bar_s {
ogs_lnode_t lnode;
uint32_t index;
uint8_t *id_node; /* Pool-Node for ID */
ogs_pfcp_bar_id_t id;

View File

@ -206,6 +206,43 @@ int ogs_pfcp_sockaddr_to_f_teid(
return OGS_OK;
}
int ogs_pfcp_f_teid_to_sockaddr(
ogs_pfcp_f_teid_t *f_teid, int f_teid_len,
ogs_sockaddr_t **addr, ogs_sockaddr_t **addr6)
{
ogs_assert(addr && addr6);
ogs_assert(f_teid);
ogs_assert(f_teid_len);
*addr = NULL;
*addr6 = NULL;
if (f_teid->ipv4 && f_teid->ipv6) {
*addr = ogs_calloc(1, sizeof(**addr));
ogs_assert(*addr);
(*addr)->sin.sin_addr.s_addr = f_teid->both.addr;
(*addr)->ogs_sa_family = AF_INET;
*addr6 = ogs_calloc(1, sizeof(**addr6));
ogs_assert(*addr6);
memcpy((*addr6)->sin6.sin6_addr.s6_addr,
f_teid->both.addr6, OGS_IPV6_LEN);
(*addr6)->ogs_sa_family = AF_INET6;
} else if (f_teid->ipv4) {
*addr = ogs_calloc(1, sizeof(**addr));
ogs_assert(*addr);
(*addr)->sin.sin_addr.s_addr = f_teid->addr;
(*addr)->ogs_sa_family = AF_INET;
} else if (f_teid->ipv6) {
*addr6 = ogs_calloc(1, sizeof(**addr6));
ogs_assert(*addr6);
memcpy((*addr6)->sin6.sin6_addr.s6_addr, f_teid->addr6, OGS_IPV6_LEN);
(*addr6)->ogs_sa_family = AF_INET6;
}
return OGS_OK;
}
int ogs_pfcp_sockaddr_to_user_plane_ip_resource_info(
ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6,
ogs_pfcp_user_plane_ip_resource_info_t *info)
@ -237,12 +274,14 @@ int ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(
if (info->v4) {
*addr = ogs_calloc(1, sizeof(**addr));
ogs_assert(*addr);
(*addr)->sin.sin_addr.s_addr = info->addr;
(*addr)->ogs_sa_family = AF_INET;
}
if (info->v6) {
*addr6 = ogs_calloc(1, sizeof(**addr6));
ogs_assert(*addr6);
memcpy((*addr6)->sin6.sin6_addr.s6_addr, info->addr6, OGS_IPV6_LEN);
(*addr6)->ogs_sa_family = AF_INET6;
}

View File

@ -41,6 +41,9 @@ int ogs_pfcp_f_seid_to_ip(ogs_pfcp_f_seid_t *f_seid, ogs_ip_t *ip);
int ogs_pfcp_sockaddr_to_f_teid(
ogs_sockaddr_t *a, ogs_sockaddr_t *b, ogs_pfcp_f_teid_t *f_teid, int *len);
int ogs_pfcp_f_teid_to_sockaddr(
ogs_pfcp_f_teid_t *f_teid, int f_teid_len,
ogs_sockaddr_t **addr, ogs_sockaddr_t **addr6);
int ogs_pfcp_sockaddr_to_user_plane_ip_resource_info(
ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6,

View File

@ -67,11 +67,9 @@ void ogs_pfcp_cp_handle_association_setup_request(
if (req->up_function_features.presence) {
if (req->up_function_features.data && req->up_function_features.len) {
ogs_pfcp_self()->up_function_features_len =
req->up_function_features.len;
memcpy(&ogs_pfcp_self()->up_function_features,
req->up_function_features.data,
ogs_pfcp_self()->up_function_features_len);
node->up_function_features_len = req->up_function_features.len;
memcpy(&node->up_function_features, req->up_function_features.data,
node->up_function_features_len);
}
}
}
@ -104,11 +102,9 @@ void ogs_pfcp_cp_handle_association_setup_response(
if (rsp->up_function_features.presence) {
if (rsp->up_function_features.data && rsp->up_function_features.len) {
ogs_pfcp_self()->up_function_features_len =
rsp->up_function_features.len;
memcpy(&ogs_pfcp_self()->up_function_features,
rsp->up_function_features.data,
ogs_pfcp_self()->up_function_features_len);
node->up_function_features_len = rsp->up_function_features.len;
memcpy(&node->up_function_features, rsp->up_function_features.data,
node->up_function_features_len);
}
}
}
@ -401,6 +397,42 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
return pdr;
}
ogs_pfcp_pdr_t *ogs_pfcp_handle_created_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_created_pdr_t *message,
uint8_t *cause_value, uint8_t *offending_ie_value)
{
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess);
ogs_assert(message);
if (message->presence == 0)
return NULL;
if (message->pdr_id.presence == 0) {
ogs_error("No PDR-ID");
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
*offending_ie_value = OGS_PFCP_PDR_ID_TYPE;
return NULL;
}
pdr = ogs_pfcp_pdr_find(sess, message->pdr_id.u16);
if (!pdr) {
ogs_error("Cannot find PDR-ID[%d] in PDR", message->pdr_id.u16);
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT;
*offending_ie_value = OGS_PFCP_PDR_ID_TYPE;
return NULL;
}
if (message->local_f_teid.presence) {
pdr->f_teid_len = message->local_f_teid.len;
memcpy(&pdr->f_teid, message->local_f_teid.data, pdr->f_teid_len);
pdr->f_teid.teid = be32toh(pdr->f_teid.teid);
}
return pdr;
}
ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_update_pdr_t *message,
uint8_t *cause_value, uint8_t *offending_ie_value)

View File

@ -54,6 +54,9 @@ void ogs_pfcp_up_handle_error_indication(
ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_create_pdr_t *message,
uint8_t *cause_value, uint8_t *offending_ie_value);
ogs_pfcp_pdr_t *ogs_pfcp_handle_created_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_created_pdr_t *message,
uint8_t *cause_value, uint8_t *offending_ie_value);
ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_update_pdr_t *message,
uint8_t *cause_value, uint8_t *offending_ie_value);

View File

@ -435,13 +435,60 @@ ED3(uint8_t spare:6;,
};
} __attribute__ ((packed)) ogs_pfcp_f_seid_t;
/*
* 8.2.3 F-TEID
*
* The following flags are coded within Octet 5:
*
* - Bit 1 V4: If this bit is set to "1" and the CH bit is not set,
* then the IPv4 address field shall be present,
* otherwise the IPv4 address field shall not be present.
* - Bit 2 V6: If this bit is set to "1" and the CH bit is not set,
* then the IPv6 address field shall be present,
* otherwise the IPv6 address field shall not be present.
* - Bit 3 CH (CHOOSE): If this bit is set to "1", then the TEID,
* IPv4 address and IPv6 address fields shall not be present and
* the UP function shall assign an F-TEID with an IP4 or an IPv6 address
* if the V4 or V6 bit is set respectively. This bit shall only be set
* by the CP function.
* - Bit 4 CHID (CHOOSE ID): If this bit is set to "1",
* then the UP function shall assign the same F-TEID to the PDRs requested
* to be created in a PFCP Session Establishment Request or
* PFCP Session Modification Request with the same CHOOSE ID value.
* This bit may only be set to "1" if the CH bit it set to "1".
* This bit shall only be set by the CP function.
* - Bit 5 to 8: Spare, for future use and set to 0.
*
* At least one of the V4 and V6 flags shall be set to "1", and
* both may be set to "1" for both scenarios:
*
* - when the CP function is allocating F-TEID, i.e. both IPv4 address field
* and IPv6 address field may be present;
* - or when the UP function is requested to allocate the F-TEID,
* i.e. when CHOOSE bit is set to "1", and the IPv4 address and
* IPv6 address fields are not present.
*
* Octet 6 to 9 (TEID) shall be present and shall contain a GTP-U TEID,
* if the CH bit in octet 5 is not set. When the TEID is present,
* if both IPv4 and IPv6 addresses are present in the F-TEID IE,
* then the TEID value shall be shared by both addresses.
*
* Octets "m to (m+3)" and/or "p to (p+15)"(IPv4 address / IPv6 address fields),
* if present, it shall contain the respective IP address values.
*
* Octet q shall be present and shall contain a binary integer value
* if the CHID bit in octet 5 is set to "1".
*/
typedef struct ogs_pfcp_f_teid_s {
ED5(uint8_t spare:4;,
uint8_t chid:1;,
uint8_t ch:1;,
uint8_t ipv6:1;,
uint8_t ipv4:1;)
uint32_t teid;
union {
uint32_t teid;
uint8_t choose_id;
};
union {
union {
uint32_t addr;
@ -451,7 +498,6 @@ ED5(uint8_t spare:4;,
uint8_t addr6[OGS_IPV6_LEN];
} both;
};
uint8_t choose_id;
};
} __attribute__ ((packed)) ogs_pfcp_f_teid_t;

View File

@ -126,7 +126,7 @@ void mme_s11_handle_create_session_response(
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (SESSION_CONTEXT_IN_ATTACH(sess)) {
if (sess && SESSION_CONTEXT_IN_ATTACH(sess)) {
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd);
nas_eps_send_attach_reject(mme_ue,
EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE);

View File

@ -646,11 +646,6 @@ void sgwc_bearer_remove_all(sgwc_sess_t *sess)
sgwc_bearer_remove(bearer);
}
sgwc_bearer_t *sgwc_bearer_find_by_sgwc_s5u_teid(uint32_t sgwc_s5u_teid)
{
return ogs_pool_find(&sgwc_bearer_pool, sgwc_s5u_teid);
}
sgwc_bearer_t *sgwc_bearer_find_by_sess_ebi(sgwc_sess_t *sess, uint8_t ebi)
{
sgwc_bearer_t *bearer = NULL;
@ -797,7 +792,6 @@ sgwc_tunnel_t *sgwc_tunnel_add(
pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(pdr);
pdr->id = pdr->index;
pdr->src_if = src_if;
if (strlen(sess->pdn.apn))
@ -818,40 +812,43 @@ sgwc_tunnel_t *sgwc_tunnel_add(
far = ogs_pfcp_far_add(&sess->pfcp);
ogs_assert(far);
far->id = far->index;
far->dst_if = dst_if;
ogs_pfcp_pdr_associate_far(pdr, far);
ogs_assert(sess->pfcp_node);
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&tunnel->local_addr, &tunnel->local_addr6);
ogs_assert(tunnel->local_addr || tunnel->local_addr6);
if (resource->info.teidri)
tunnel->local_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
tunnel->index, resource->info.teidri,
resource->info.teid_range);
else
tunnel->local_teid = tunnel->index;
if (sess->pfcp_node->up_function_features.ftup) {
pdr->f_teid.ch = 1;
pdr->f_teid_len = 1;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_copyaddrinfo(&tunnel->local_addr, &sess->pfcp_node->addr);
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ogs_copyaddrinfo(&tunnel->local_addr6, &sess->pfcp_node->addr);
else
ogs_assert_if_reached();
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&tunnel->local_addr, &tunnel->local_addr6);
if (resource->info.teidri)
tunnel->local_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
tunnel->index, resource->info.teidri,
resource->info.teid_range);
else
tunnel->local_teid = tunnel->index;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_copyaddrinfo(&tunnel->local_addr, &sess->pfcp_node->addr);
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ogs_copyaddrinfo(&tunnel->local_addr6, &sess->pfcp_node->addr);
else
ogs_assert_if_reached();
tunnel->local_teid = tunnel->index;
}
ogs_assert(tunnel->local_addr || tunnel->local_addr6);
tunnel->local_teid = tunnel->index;
ogs_pfcp_sockaddr_to_f_teid(tunnel->local_addr, tunnel->local_addr6,
&pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = tunnel->local_teid;
}
ogs_pfcp_sockaddr_to_f_teid(tunnel->local_addr, tunnel->local_addr6,
&pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = tunnel->local_teid;
tunnel->pdr = pdr;
tunnel->far = far;
@ -891,9 +888,23 @@ void sgwc_tunnel_remove_all(sgwc_bearer_t *bearer)
sgwc_tunnel_remove(tunnel);
}
sgwc_tunnel_t *sgwc_tunnel_find_by_teid(uint32_t teid)
sgwc_tunnel_t *sgwc_tunnel_find_by_teid(sgwc_ue_t *sgwc_ue, uint32_t teid)
{
return ogs_pool_find(&sgwc_tunnel_pool, teid);
sgwc_sess_t *sess = NULL;
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *tunnel = NULL;
ogs_assert(sgwc_ue);
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_list_for_each(&bearer->tunnel_list, tunnel) {
if (tunnel->local_teid == teid) return tunnel;
}
}
}
return NULL;
}
sgwc_tunnel_t *sgwc_tunnel_find_by_interface_type(
@ -909,6 +920,28 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_interface_type(
return NULL;
}
sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
sgwc_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id)
{
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *tunnel = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_list_for_each(&bearer->tunnel_list, tunnel) {
pdr = tunnel->pdr;
ogs_assert(pdr);
if (pdr->id == pdr_id) return tunnel;
}
}
return NULL;
}
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer)
{
ogs_assert(bearer);

View File

@ -179,8 +179,6 @@ sgwc_sess_t *sgwc_sess_find_by_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi);
sgwc_bearer_t *sgwc_bearer_add(sgwc_sess_t *sess);
int sgwc_bearer_remove(sgwc_bearer_t *bearer);
void sgwc_bearer_remove_all(sgwc_sess_t *sess);
sgwc_bearer_t *sgwc_bearer_find_by_sgwc_s5u_teid(
uint32_t sgwc_s5u_teid);
sgwc_bearer_t *sgwc_bearer_find_by_sess_ebi(
sgwc_sess_t *sess, uint8_t ebi);
sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(
@ -194,9 +192,11 @@ sgwc_tunnel_t *sgwc_tunnel_add(
sgwc_bearer_t *bearer, uint8_t interface_type);
int sgwc_tunnel_remove(sgwc_tunnel_t *tunnel);
void sgwc_tunnel_remove_all(sgwc_bearer_t *bearer);
sgwc_tunnel_t *sgwc_tunnel_find_by_teid(uint32_t teid);
sgwc_tunnel_t *sgwc_tunnel_find_by_teid(sgwc_ue_t *sgwc_ue, uint32_t teid);
sgwc_tunnel_t *sgwc_tunnel_find_by_interface_type(
sgwc_bearer_t *bearer, uint8_t interface_type);
sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
sgwc_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id);
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer);
sgwc_tunnel_t *sgwc_ul_tunnel_in_bearer(sgwc_bearer_t *bearer);

View File

@ -235,6 +235,7 @@ void sgwc_s11_handle_modify_bearer_request(
uint16_t decoded;
uint64_t flags = 0;
sgwc_sess_t *sess = NULL;
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *dl_tunnel = NULL;
ogs_pfcp_far_t *far = NULL;
@ -291,6 +292,10 @@ void sgwc_s11_handle_modify_bearer_request(
return;
}
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
ogs_assert(dl_tunnel);
@ -332,8 +337,10 @@ void sgwc_s11_handle_modify_bearer_request(
if (memcmp(&dl_tunnel->remote_ip, &zero_ip, sizeof(ogs_ip_t)) != 0 &&
memcmp(&dl_tunnel->remote_ip, &remote_ip, sizeof(ogs_ip_t)) != 0) {
ogs_assert(sess->pfcp_node);
/* eNB IP is changed during handover */
if (ogs_pfcp_self()->up_function_features.empu) {
if (sess->pfcp_node->up_function_features.empu) {
flags |= OGS_PFCP_MODIFY_END_MARKER;
} else {
ogs_error("SGW-U does not support End Marker");
@ -519,12 +526,14 @@ void sgwc_s11_handle_create_bearer_response(
return;
}
ogs_assert(sgwc_ue);
/* Correlate with SGW-S1U-TEID */
sgw_s1u_teid = rsp->bearer_contexts.s4_u_sgsn_f_teid.data;
ogs_assert(sgw_s1u_teid);
/* Find the Tunnel by SGW-S1U-TEID */
ul_tunnel = sgwc_tunnel_find_by_teid(be32toh(sgw_s1u_teid->teid));
ul_tunnel = sgwc_tunnel_find_by_teid(sgwc_ue, be32toh(sgw_s1u_teid->teid));
ogs_assert(ul_tunnel);
bearer = ul_tunnel->bearer;
ogs_assert(bearer);

View File

@ -84,6 +84,7 @@ void sgwc_sxa_handle_session_establishment_response(
{
int rv, len = 0;
uint8_t cause_value = 0;
ogs_pfcp_f_seid_t *up_f_seid = NULL;
ogs_gtp_f_teid_t sgw_s5c_teid, sgw_s5u_teid;
@ -123,6 +124,11 @@ void sgwc_sxa_handle_session_establishment_response(
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (pfcp_rsp->created_pdr[0].presence == 0) {
ogs_error("No Created PDR");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (pfcp_rsp->cause.presence) {
if (pfcp_rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("PFCP Cause [%d] : Not Accepted", pfcp_rsp->cause.u8);
@ -133,6 +139,48 @@ void sgwc_sxa_handle_session_establishment_response(
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
int i;
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_assert(sess);
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
sgwc_tunnel_t *tunnel = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &pfcp_rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
tunnel = sgwc_tunnel_find_by_pdr_id(sess, pdr->id);
if (!tunnel) {
pfcp_cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
break;
}
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (tunnel->local_addr)
ogs_freeaddrinfo(tunnel->local_addr);
if (tunnel->local_addr6)
ogs_freeaddrinfo(tunnel->local_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&tunnel->local_addr, &tunnel->local_addr6);
tunnel->local_teid = pdr->f_teid.teid;
}
}
cause_value = gtp_cause_from_pfcp(pfcp_cause_value);
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (sess) sgwc_ue = sess->sgwc_ue;
ogs_gtp_send_error_message(
@ -148,6 +196,15 @@ void sgwc_sxa_handle_session_establishment_response(
dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
ogs_assert(dl_tunnel);
if (dl_tunnel->local_addr == NULL && dl_tunnel->local_addr6 == NULL) {
ogs_error("No UP F-TEID");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_GRE_KEY_NOT_FOUND);
return;
}
/* UP F-SEID */
up_f_seid = pfcp_rsp->up_f_seid.data;
ogs_assert(up_f_seid);
@ -195,6 +252,7 @@ void sgwc_sxa_handle_session_establishment_response(
memset(&sgw_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t));
sgw_s5u_teid.teid = htobe32(dl_tunnel->local_teid);
sgw_s5u_teid.interface_type = dl_tunnel->interface_type;
ogs_assert(dl_tunnel->local_addr || dl_tunnel->local_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
dl_tunnel->local_addr, dl_tunnel->local_addr6, &sgw_s5u_teid, &len);
ogs_assert(rv == OGS_OK);
@ -265,6 +323,46 @@ void sgwc_sxa_handle_session_modification_response(
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_assert(sess);
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
sgwc_tunnel_t *tunnel = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &pfcp_rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
tunnel = sgwc_tunnel_find_by_pdr_id(sess, pdr->id);
if (!tunnel) {
pfcp_cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
break;
}
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (tunnel->local_addr)
ogs_freeaddrinfo(tunnel->local_addr);
if (tunnel->local_addr6)
ogs_freeaddrinfo(tunnel->local_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&tunnel->local_addr, &tunnel->local_addr6);
tunnel->local_teid = pdr->f_teid.teid;
}
}
cause_value = gtp_cause_from_pfcp(pfcp_cause_value);
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (sess) sgwc_ue = sess->sgwc_ue;
if (flags & OGS_PFCP_MODIFY_CREATE) {
@ -353,6 +451,7 @@ void sgwc_sxa_handle_session_modification_response(
memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp_f_teid_t));
sgw_s1u_teid.interface_type = ul_tunnel->interface_type;
sgw_s1u_teid.teid = htobe32(ul_tunnel->local_teid);
ogs_assert(ul_tunnel->local_addr || ul_tunnel->local_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
ul_tunnel->local_addr, ul_tunnel->local_addr6,
&sgw_s1u_teid, &len);
@ -398,6 +497,7 @@ void sgwc_sxa_handle_session_modification_response(
memset(&sgw_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t));
sgw_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_SGW_GTP_U;
sgw_s5u_teid.teid = htobe32(dl_tunnel->local_teid);
ogs_assert(dl_tunnel->local_addr || dl_tunnel->local_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
dl_tunnel->local_addr, dl_tunnel->local_addr6,
&sgw_s5u_teid, &len);
@ -485,6 +585,8 @@ void sgwc_sxa_handle_session_modification_response(
rsp_dl_teid[i].interface_type =
tunnel->interface_type;
rsp_dl_teid[i].teid = htobe32(tunnel->local_teid);
ogs_assert(
tunnel->local_addr || tunnel->local_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
tunnel->local_addr, tunnel->local_addr6,
&rsp_dl_teid[i], &len);
@ -504,6 +606,8 @@ void sgwc_sxa_handle_session_modification_response(
rsp_ul_teid[i].teid = htobe32(tunnel->local_teid);
rsp_ul_teid[i].interface_type =
tunnel->interface_type;
ogs_assert(
tunnel->local_addr || tunnel->local_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
tunnel->local_addr, tunnel->local_addr6,
&rsp_ul_teid[i], &len);
@ -663,6 +767,7 @@ void sgwc_sxa_handle_session_modification_response(
memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp_f_teid_t));
sgw_s1u_teid.interface_type = ul_tunnel->interface_type;
sgw_s1u_teid.teid = htobe32(ul_tunnel->local_teid);
ogs_assert(ul_tunnel->local_addr || ul_tunnel->local_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
ul_tunnel->local_addr, ul_tunnel->local_addr6,
&sgw_s1u_teid, &len);

View File

@ -24,6 +24,7 @@ ogs_pkbuf_t *sgwu_sxa_build_session_establishment_response(uint8_t type,
{
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_establishment_response_t *rsp = NULL;
ogs_pkbuf_t *pkbuf = NULL;
int i = 0;
@ -58,18 +59,19 @@ ogs_pkbuf_t *sgwu_sxa_build_session_establishment_response(uint8_t type,
rsp->up_f_seid.data = &f_seid;
rsp->up_f_seid.len = len;
ogs_pfcp_pdrbuf_init();
/* Created PDR */
for (i = 0; i < num_of_created_pdr; i++) {
ogs_pfcp_tlv_created_pdr_t *message = &rsp->created_pdr[i];
ogs_assert(message);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = created_pdr[i]->id;
ogs_pfcp_build_created_pdr(&rsp->created_pdr[i], i, created_pdr[i]);
}
pfcp_message.h.type = type;
return ogs_pfcp_build_msg(&pfcp_message);
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
ogs_pfcp_pdrbuf_clear();
return pkbuf;
}
ogs_pkbuf_t *sgwu_sxa_build_session_modification_response(uint8_t type,
@ -77,6 +79,7 @@ ogs_pkbuf_t *sgwu_sxa_build_session_modification_response(uint8_t type,
{
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_modification_response_t *rsp = NULL;
ogs_pkbuf_t *pkbuf = NULL;
int i = 0;
@ -89,18 +92,19 @@ ogs_pkbuf_t *sgwu_sxa_build_session_modification_response(uint8_t type,
rsp->cause.presence = 1;
rsp->cause.u8 = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
ogs_pfcp_pdrbuf_init();
/* Created PDR */
for (i = 0; i < num_of_created_pdr; i++) {
ogs_pfcp_tlv_created_pdr_t *message = &rsp->created_pdr[i];
ogs_assert(message);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = created_pdr[i]->id;
ogs_pfcp_build_created_pdr(&rsp->created_pdr[i], i, created_pdr[i]);
}
pfcp_message.h.type = type;
return ogs_pfcp_build_msg(&pfcp_message);
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
ogs_pfcp_pdrbuf_clear();
return pkbuf;
}
ogs_pkbuf_t *sgwu_sxa_build_session_deletion_response(uint8_t type,

View File

@ -115,8 +115,40 @@ void sgwu_sxa_handle_session_establishment_request(
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len)
if (pdr->f_teid_len) {
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
if (sgwu_self()->gtpu_sock)
addr = &sgwu_self()->gtpu_sock->local_addr;
if (sgwu_self()->gtpu_sock6)
addr6 = &sgwu_self()->gtpu_sock6->local_addr;
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = pdr->index;
}
}
ogs_pfcp_pdr_hash_set(pdr);
}
}
/* Send Buffered Packet to gNB */
@ -257,8 +289,40 @@ void sgwu_sxa_handle_session_modification_request(
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len)
if (pdr->f_teid_len) {
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
if (sgwu_self()->gtpu_sock)
addr = &sgwu_self()->gtpu_sock->local_addr;
if (sgwu_self()->gtpu_sock6)
addr6 = &sgwu_self()->gtpu_sock6->local_addr;
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = pdr->index;
}
}
ogs_pfcp_pdr_hash_set(pdr);
}
}
/* Send Buffered Packet to gNB */

View File

@ -19,6 +19,7 @@
#include "bearer-binding.h"
#include "s5c-build.h"
#include "pfcp-path.h"
#include "ipfw/ipfw2.h"
@ -203,7 +204,6 @@ void smf_bearer_binding(smf_sess_t *sess)
ogs_pcc_rule_t *pcc_rule = &sess->pcc_rule[i];
int bearer_created = 0;
int qos_presence = 0;
ogs_gtp_tft_t tft;
ogs_assert(pcc_rule);
if (pcc_rule->name == NULL) {
@ -334,28 +334,40 @@ void smf_bearer_binding(smf_sess_t *sess)
}
}
memset(&tft, 0, sizeof tft);
if (pcc_rule->num_of_flow)
encode_traffic_flow_template(&tft, bearer);
memset(&h, 0, sizeof(ogs_gtp_header_t));
if (bearer_created == 1) {
h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE;
h.teid = sess->sgw_s5c_teid;
/* Setup QER */
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) {
ogs_pfcp_qer_t *qer = NULL;
/* TFT is mandatory in
* activate dedicated EPS bearer context request */
ogs_assert(pcc_rule->num_of_flow);
/* Only 1 QER is used per bearer */
qer = bearer->qer;
if (!qer) {
qer = ogs_pfcp_qer_add(&sess->pfcp);
ogs_assert(qer);
bearer->qer = qer;
}
pkbuf = smf_s5c_build_create_bearer_request(
h.type, bearer, pcc_rule->num_of_flow ? &tft : NULL);
ogs_expect_or_return(pkbuf);
ogs_pfcp_pdr_associate_qer(bearer->dl_pdr, qer);
ogs_pfcp_pdr_associate_qer(bearer->ul_pdr, qer);
xact = ogs_gtp_xact_local_create(
sess->gnode, &h, pkbuf, timeout, sess);
ogs_expect_or_return(xact);
qer->mbr.uplink = bearer->qos.mbr.uplink;
qer->mbr.downlink = bearer->qos.mbr.downlink;
qer->gbr.uplink = bearer->qos.gbr.uplink;
qer->gbr.downlink = bearer->qos.gbr.downlink;
}
smf_epc_pfcp_send_bearer_modification_request(
bearer, OGS_PFCP_MODIFY_CREATE);
} else {
ogs_gtp_tft_t tft;
memset(&tft, 0, sizeof tft);
if (pcc_rule->num_of_flow)
encode_traffic_flow_template(&tft, bearer);
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE;
h.teid = sess->sgw_s5c_teid;
@ -373,10 +385,10 @@ void smf_bearer_binding(smf_sess_t *sess)
xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE;
if (qos_presence)
xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE;
}
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
} else if (pcc_rule->type == OGS_PCC_RULE_TYPE_REMOVE) {
bearer = smf_bearer_find_by_name(sess, pcc_rule->name);
@ -407,3 +419,34 @@ void smf_bearer_binding(smf_sess_t *sess)
}
}
}
void smf_gtp_send_create_bearer_request(smf_bearer_t *bearer)
{
int rv;
smf_sess_t *sess = NULL;
ogs_gtp_xact_t *xact = NULL;
ogs_gtp_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_tft_t tft;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE;
h.teid = sess->sgw_s5c_teid;
memset(&tft, 0, sizeof tft);
encode_traffic_flow_template(&tft, bearer);
pkbuf = smf_s5c_build_create_bearer_request(h.type, bearer, &tft);
ogs_expect_or_return(pkbuf);
xact = ogs_gtp_xact_local_create(sess->gnode, &h, pkbuf, timeout, sess);
ogs_expect_or_return(xact);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}

View File

@ -27,6 +27,7 @@ extern "C" {
#endif
void smf_bearer_binding(smf_sess_t *sess);
void smf_gtp_send_create_bearer_request(smf_bearer_t *bearer);
#ifdef __cplusplus
}

View File

@ -1176,7 +1176,6 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
dl_pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(dl_pdr);
dl_pdr->id = dl_pdr->index;
qos_flow->dl_pdr = dl_pdr;
dl_pdr->src_if = OGS_PFCP_INTERFACE_CORE;
@ -1186,7 +1185,6 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
ul_pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(ul_pdr);
ul_pdr->id = ul_pdr->index;
qos_flow->ul_pdr = ul_pdr;
ul_pdr->src_if = OGS_PFCP_INTERFACE_ACCESS;
@ -1209,7 +1207,6 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
dl_far = ogs_pfcp_far_add(&sess->pfcp);
ogs_assert(dl_far);
dl_far->id = dl_far->index;
qos_flow->dl_far = dl_far;
dl_far->dst_if = OGS_PFCP_INTERFACE_ACCESS;
@ -1217,7 +1214,6 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
ul_far = ogs_pfcp_far_add(&sess->pfcp);
ogs_assert(ul_far);
ul_far->id = ul_far->index;
qos_flow->ul_far = ul_far;
ul_far->dst_if = OGS_PFCP_INTERFACE_CORE;
@ -1225,7 +1221,6 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
qer = ogs_pfcp_qer_add(&sess->pfcp);
ogs_assert(qer);
qer->id = qer->index;
qos_flow->qer = qer;
ogs_pfcp_pdr_associate_qer(dl_pdr, qer);
@ -1283,7 +1278,6 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
dl_pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(dl_pdr);
dl_pdr->id = dl_pdr->index;
bearer->dl_pdr = dl_pdr;
dl_pdr->src_if = OGS_PFCP_INTERFACE_CORE;
@ -1293,7 +1287,6 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
ul_pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(ul_pdr);
ul_pdr->id = ul_pdr->index;
bearer->ul_pdr = ul_pdr;
ul_pdr->src_if = OGS_PFCP_INTERFACE_ACCESS;
@ -1316,7 +1309,6 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
dl_far = ogs_pfcp_far_add(&sess->pfcp);
ogs_assert(dl_far);
dl_far->id = dl_far->index;
bearer->dl_far = dl_far;
dl_far->dst_if = OGS_PFCP_INTERFACE_ACCESS;
@ -1324,42 +1316,46 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
ul_far = ogs_pfcp_far_add(&sess->pfcp);
ogs_assert(ul_far);
ul_far->id = ul_far->index;
bearer->ul_far = ul_far;
ul_far->dst_if = OGS_PFCP_INTERFACE_CORE;
ogs_pfcp_pdr_associate_far(ul_pdr, ul_far);
ogs_assert(sess->pfcp_node);
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
if (resource->info.teidri)
bearer->pgw_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
bearer->index, resource->info.teidri,
resource->info.teid_range);
else
bearer->pgw_s5u_teid = bearer->index;
if (sess->pfcp_node->up_function_features.ftup) {
ul_pdr->f_teid.ch = 1;
ul_pdr->f_teid_len = 1;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_copyaddrinfo(&bearer->pgw_s5u_addr, &sess->pfcp_node->addr);
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ogs_copyaddrinfo(&bearer->pgw_s5u_addr6, &sess->pfcp_node->addr);
else
ogs_assert_if_reached();
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
if (resource->info.teidri)
bearer->pgw_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
bearer->index, resource->info.teidri,
resource->info.teid_range);
else
bearer->pgw_s5u_teid = bearer->index;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_copyaddrinfo(&bearer->pgw_s5u_addr, &sess->pfcp_node->addr);
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ogs_copyaddrinfo(
&bearer->pgw_s5u_addr6, &sess->pfcp_node->addr);
else
ogs_assert_if_reached();
bearer->pgw_s5u_teid = bearer->index;
}
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
bearer->pgw_s5u_teid = bearer->index;
ogs_pfcp_sockaddr_to_f_teid(bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
&ul_pdr->f_teid, &ul_pdr->f_teid_len);
ul_pdr->f_teid.teid = bearer->pgw_s5u_teid;
}
ogs_pfcp_sockaddr_to_f_teid(bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
&ul_pdr->f_teid, &ul_pdr->f_teid_len);
ul_pdr->f_teid.teid = bearer->pgw_s5u_teid;
bearer->sess = sess;
ogs_list_add(&sess->bearer_list, bearer);
@ -1415,9 +1411,19 @@ smf_bearer_t *smf_bearer_find(uint32_t index)
return ogs_pool_find(&smf_bearer_pool, index);
}
smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(uint32_t pgw_s5u_teid)
smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(
smf_sess_t *sess, uint32_t pgw_s5u_teid)
{
return smf_bearer_find(pgw_s5u_teid);
smf_bearer_t *bearer = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->bearer_list, bearer) {
if (bearer->pgw_s5u_teid == pgw_s5u_teid)
return bearer;
}
return NULL;
}
smf_bearer_t *smf_bearer_find_by_ebi(smf_sess_t *sess, uint8_t ebi)
@ -1426,15 +1432,12 @@ smf_bearer_t *smf_bearer_find_by_ebi(smf_sess_t *sess, uint8_t ebi)
ogs_assert(sess);
bearer = smf_bearer_first(sess);
while (bearer) {
ogs_list_for_each(&sess->bearer_list, bearer) {
if (bearer->ebi == ebi)
break;
bearer = smf_bearer_next(bearer);
return bearer;
}
return bearer;
return NULL;
}
smf_bearer_t *smf_bearer_find_by_name(smf_sess_t *sess, char *name)
@ -1444,12 +1447,9 @@ smf_bearer_t *smf_bearer_find_by_name(smf_sess_t *sess, char *name)
ogs_assert(sess);
ogs_assert(name);
bearer = smf_bearer_first(sess);
while (bearer) {
ogs_list_for_each(&sess->bearer_list, bearer) {
if (bearer->name && strcmp(bearer->name, name) == 0)
return bearer;
bearer = smf_bearer_next(bearer);
}
return NULL;
@ -1493,6 +1493,29 @@ smf_bearer_t *smf_bearer_find_by_qci_arp(smf_sess_t *sess,
return NULL;
}
smf_bearer_t *smf_bearer_find_by_pdr_id(
smf_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id)
{
smf_bearer_t *bearer = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_pfcp_pdr_t *dl_pdr = NULL;
ogs_pfcp_pdr_t *ul_pdr = NULL;
dl_pdr = bearer->dl_pdr;
ogs_assert(dl_pdr);
ul_pdr = bearer->ul_pdr;
ogs_assert(ul_pdr);
if (dl_pdr->id == pdr_id || ul_pdr->id == pdr_id)
return bearer;
}
return NULL;
}
smf_bearer_t *smf_default_bearer_in_sess(smf_sess_t *sess)
{
return smf_bearer_first(sess);

View File

@ -327,7 +327,8 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess);
int smf_bearer_remove(smf_bearer_t *bearer);
void smf_bearer_remove_all(smf_sess_t *sess);
smf_bearer_t *smf_bearer_find(uint32_t index);
smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(uint32_t pgw_s5u_teid);
smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(
smf_sess_t *sess, uint32_t pgw_s5u_teid);
smf_bearer_t *smf_bearer_find_by_ebi(smf_sess_t *sess, uint8_t ebi);
smf_bearer_t *smf_bearer_find_by_name(smf_sess_t *sess, char *name);
smf_bearer_t *smf_bearer_find_by_qci_arp(smf_sess_t *sess,
@ -335,6 +336,8 @@ smf_bearer_t *smf_bearer_find_by_qci_arp(smf_sess_t *sess,
uint8_t priority_level,
uint8_t pre_emption_capability,
uint8_t pre_emption_vulnerability);
smf_bearer_t *smf_bearer_find_by_pdr_id(
smf_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id);
smf_bearer_t *smf_default_bearer_in_sess(smf_sess_t *sess);
bool smf_bearer_is_default(smf_bearer_t *bearer);
smf_bearer_t *smf_bearer_first(smf_sess_t *sess);

View File

@ -124,7 +124,6 @@ void smf_gx_handle_cca_initial_request(
if (!qer) {
qer = ogs_pfcp_qer_add(&sess->pfcp);
ogs_assert(qer);
qer->id = qer->index;
bearer->qer = qer;
}

View File

@ -99,8 +99,13 @@ void smf_5gc_n4_handle_session_establishment_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_establishment_response_t *rsp)
{
int i;
ogs_sbi_session_t *session = NULL;
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_pfcp_f_seid_t *up_f_seid = NULL;
ogs_assert(xact);
@ -121,6 +126,11 @@ void smf_5gc_n4_handle_session_establishment_response(
return;
}
if (rsp->created_pdr[0].presence == 0) {
ogs_error("No Created PDR");
return;
}
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_error("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
@ -133,6 +143,42 @@ void smf_5gc_n4_handle_session_establishment_response(
ogs_assert(sess);
pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (sess->upf_n3_addr)
ogs_freeaddrinfo(sess->upf_n3_addr);
if (sess->upf_n3_addr6)
ogs_freeaddrinfo(sess->upf_n3_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&sess->upf_n3_addr, &sess->upf_n3_addr6);
sess->upf_n3_teid = pdr->f_teid.teid;
}
}
if (pfcp_cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_error("PFCP Cause [%d] : Not Accepted", pfcp_cause_value);
return;
}
if (sess->upf_n3_addr == NULL && sess->upf_n3_addr6 == NULL) {
ogs_error("No UP F-TEID");
return;
}
/* UP F-SEID */
up_f_seid = rsp->up_f_seid.data;
ogs_assert(up_f_seid);
@ -181,6 +227,41 @@ void smf_5gc_n4_handle_session_modification_response(
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
}
if (status == OGS_SBI_HTTP_STATUS_OK) {
int i;
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_assert(sess);
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (sess->upf_n3_addr)
ogs_freeaddrinfo(sess->upf_n3_addr);
if (sess->upf_n3_addr6)
ogs_freeaddrinfo(sess->upf_n3_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&sess->upf_n3_addr, &sess->upf_n3_addr6);
sess->upf_n3_teid = pdr->f_teid.teid;
}
}
status = sbi_status_from_pfcp(pfcp_cause_value);
}
if (status != OGS_SBI_HTTP_STATUS_OK) {
char *strerror = ogs_msprintf(
"PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
@ -192,6 +273,12 @@ void smf_5gc_n4_handle_session_modification_response(
ogs_assert(sess);
if (sess->upf_n3_addr == NULL && sess->upf_n3_addr6 == NULL) {
smf_sbi_send_sm_context_update_error(session, status, "No UP F_TEID",
NULL, NULL, NULL);
return;
}
if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
/* ACTIVATED Is NOT Inlcuded in RESPONSE */
smf_sbi_send_sm_context_updated_data(sess, session, 0);
@ -274,7 +361,10 @@ void smf_epc_n4_handle_session_establishment_response(
ogs_pfcp_session_establishment_response_t *rsp)
{
uint8_t cause_value = 0;
smf_bearer_t *bearer = NULL;
ogs_gtp_xact_t *gtp_xact = NULL;
ogs_pfcp_f_seid_t *up_f_seid = NULL;
ogs_assert(xact);
@ -297,6 +387,11 @@ void smf_epc_n4_handle_session_establishment_response(
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->created_pdr[0].presence == 0) {
ogs_error("No Created PDR");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
@ -307,6 +402,47 @@ void smf_epc_n4_handle_session_establishment_response(
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value == OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
int i;
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_assert(sess);
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
if (!bearer) {
pfcp_cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
break;
}
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (bearer->pgw_s5u_addr)
ogs_freeaddrinfo(bearer->pgw_s5u_addr);
if (bearer->pgw_s5u_addr)
ogs_freeaddrinfo(bearer->pgw_s5u_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
bearer->pgw_s5u_teid = pdr->f_teid.teid;
}
}
cause_value = gtp_cause_from_pfcp(pfcp_cause_value);
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
@ -314,6 +450,16 @@ void smf_epc_n4_handle_session_establishment_response(
}
ogs_assert(sess);
bearer = smf_default_bearer_in_sess(sess);
ogs_assert(bearer);
if (bearer->pgw_s5u_addr == NULL && bearer->pgw_s5u_addr6 == NULL) {
ogs_error("No UP F-TEID");
ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP_CAUSE_GRE_KEY_NOT_FOUND);
return;
}
/* UP F-SEID */
up_f_seid = rsp->up_f_seid.data;
@ -329,9 +475,14 @@ void smf_epc_n4_handle_session_modification_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_modification_response_t *rsp)
{
int i;
smf_bearer_t *bearer = NULL;
uint64_t flags = 0;
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_assert(xact);
ogs_assert(rsp);
@ -342,8 +493,63 @@ void smf_epc_n4_handle_session_modification_response(
ogs_pfcp_xact_commit(xact);
if (flags & OGS_PFCP_MODIFY_REMOVE)
if (!sess) {
ogs_error("No Context");
return;
}
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_error("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
return;
}
} else {
ogs_error("No Cause");
return;
}
ogs_assert(sess);
pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
ogs_pfcp_pdr_t *pdr = NULL;
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (bearer->pgw_s5u_addr)
ogs_freeaddrinfo(bearer->pgw_s5u_addr);
if (bearer->pgw_s5u_addr)
ogs_freeaddrinfo(bearer->pgw_s5u_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
bearer->pgw_s5u_teid = pdr->f_teid.teid;
}
}
if (pfcp_cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_error("PFCP Cause [%d] : Not Accepted", pfcp_cause_value);
return;
}
if (flags & OGS_PFCP_MODIFY_CREATE) {
smf_gtp_send_create_bearer_request(bearer);
} else if (flags & OGS_PFCP_MODIFY_REMOVE) {
smf_bearer_remove(bearer);
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
/* Nothing */
}
}
void smf_epc_n4_handle_session_deletion_response(

View File

@ -79,6 +79,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
UPTransportLayerInformation->choice.gTPTunnel = gTPTunnel;
ogs_assert(sess->upf_n3_addr || sess->upf_n3_addr6);
ogs_sockaddr_to_ip(sess->upf_n3_addr, sess->upf_n3_addr6, &upf_n3_ip);
ogs_asn_ip_to_BIT_STRING(&upf_n3_ip, &gTPTunnel->transportLayerAddress);
ogs_asn_uint32_to_OCTET_STRING(sess->upf_n3_teid, &gTPTunnel->gTP_TEID);

View File

@ -235,45 +235,6 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_session_t *session,
return false;
}
/* Setup GTP-U Tunnel */
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&sess->upf_n3_addr, &sess->upf_n3_addr6);
ogs_assert(sess->upf_n3_addr || sess->upf_n3_addr6);
if (resource->info.teidri)
sess->upf_n3_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
sess->index, resource->info.teidri,
resource->info.teid_range);
else
sess->upf_n3_teid = sess->index;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_copyaddrinfo(&sess->upf_n3_addr, &sess->pfcp_node->addr);
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ogs_copyaddrinfo(&sess->upf_n3_addr6, &sess->pfcp_node->addr);
else
ogs_assert_if_reached();
ogs_assert(sess->upf_n3_addr || sess->upf_n3_addr6);
sess->upf_n3_teid = sess->index;
}
ogs_debug("UPF TEID:[0x%x], IPv4:[%s] IPv6:[%s]",
sess->upf_n3_teid,
sess->upf_n3_addr ? OGS_ADDR(sess->upf_n3_addr, buf1) : "",
sess->upf_n3_addr6 ? OGS_ADDR(sess->upf_n3_addr6, buf2) : "");
/* UE IP Address */
smf_sess_set_ue_ip(sess);
ogs_info("UE SUPI:[%s] DNN:[%s] IPv4:[%s] IPv6:[%s]",
smf_ue->supi, sess->pdn.dnn,
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
/*********************************************************************
* Send HTTP_STATUS_CREATED(/nsmf-pdusession/v1/sm-context) to the AMF
*********************************************************************/
@ -299,7 +260,6 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_session_t *session,
ogs_free(sendmsg.http.location);
/*********************************************************************
* Send PFCP Session Establiashment Request to the UPF
*********************************************************************/
@ -324,14 +284,50 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_session_t *session,
ogs_assert(ul_pdr);
/* Set UE IP Address to the Default DL PDR */
smf_sess_set_ue_ip(sess);
ogs_pfcp_paa_to_ue_ip_addr(&sess->pdn.paa,
&dl_pdr->ue_ip_addr, &dl_pdr->ue_ip_addr_len);
dl_pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST;
ogs_info("UE SUPI:[%s] DNN:[%s] IPv4:[%s] IPv6:[%s]",
smf_ue->supi, sess->pdn.dnn,
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
/* Set UPF-N3 TEID & ADDR to the Default UL PDR */
ogs_pfcp_sockaddr_to_f_teid(sess->upf_n3_addr, sess->upf_n3_addr6,
&ul_pdr->f_teid, &ul_pdr->f_teid_len);
ul_pdr->f_teid.teid = sess->upf_n3_teid;
if (sess->pfcp_node->up_function_features.ftup) {
ul_pdr->f_teid.ch = 1;
ul_pdr->f_teid_len = 1;
} else {
resource = ogs_pfcp_gtpu_resource_find(
&sess->pfcp_node->gtpu_resource_list,
sess->pdn.dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&sess->upf_n3_addr, &sess->upf_n3_addr6);
if (resource->info.teidri)
sess->upf_n3_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
sess->index, resource->info.teidri,
resource->info.teid_range);
else
sess->upf_n3_teid = sess->index;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_copyaddrinfo(&sess->upf_n3_addr, &sess->pfcp_node->addr);
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ogs_copyaddrinfo(&sess->upf_n3_addr6, &sess->pfcp_node->addr);
else
ogs_assert_if_reached();
sess->upf_n3_teid = sess->index;
}
ogs_assert(sess->upf_n3_addr || sess->upf_n3_addr6);
ogs_pfcp_sockaddr_to_f_teid(sess->upf_n3_addr, sess->upf_n3_addr6,
&ul_pdr->f_teid, &ul_pdr->f_teid_len);
ul_pdr->f_teid.teid = sess->upf_n3_teid;
}
/* Default PDRs is set to lowest precedence(highest precedence value) */
dl_pdr->precedence = 0xffffffff;

View File

@ -143,6 +143,7 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
memset(&pgw_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t));
pgw_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid.teid = htobe32(bearer->pgw_s5u_teid);
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6, &pgw_s5u_teid, &len);
ogs_assert(rv == OGS_OK);
@ -238,6 +239,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request(
memset(&pgw_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t));
pgw_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid.teid = htobe32(bearer->pgw_s5u_teid);
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
rv = ogs_gtp_sockaddr_to_f_teid(
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6, &pgw_s5u_teid, &len);
ogs_assert(rv == OGS_OK);

View File

@ -323,11 +323,11 @@ void smf_s5c_handle_create_bearer_response(
/* Correlate with PGW-S5U-TEID */
pgw_s5u_teid = rsp->bearer_contexts.s5_s8_u_pgw_f_teid.data;
ogs_assert(pgw_s5u_teid);
ogs_expect_or_return(pgw_s5u_teid);
/* Find the Bearer by PGW-S5U-TEID */
bearer = smf_bearer_find_by_pgw_s5u_teid(be32toh(pgw_s5u_teid->teid));
ogs_assert(bearer);
bearer = smf_bearer_find_by_pgw_s5u_teid(sess, be32toh(pgw_s5u_teid->teid));
ogs_expect_or_return(bearer);
/* Set EBI */
bearer->ebi = rsp->bearer_contexts.eps_bearer_id.u8;
@ -350,31 +350,8 @@ void smf_s5c_handle_create_bearer_response(
&dl_far->outer_header_creation, &dl_far->outer_header_creation_len);
dl_far->outer_header_creation.teid = bearer->sgw_s5u_teid;
/* Setup QER */
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) {
ogs_pfcp_qer_t *qer = NULL;
/* Only 1 QER is used per bearer */
qer = bearer->qer;
if (!qer) {
qer = ogs_pfcp_qer_add(&sess->pfcp);
ogs_assert(qer);
qer->id = qer->index;
bearer->qer = qer;
}
ogs_pfcp_pdr_associate_qer(bearer->dl_pdr, qer);
ogs_pfcp_pdr_associate_qer(bearer->ul_pdr, qer);
qer->mbr.uplink = bearer->qos.mbr.uplink;
qer->mbr.downlink = bearer->qos.mbr.downlink;
qer->gbr.uplink = bearer->qos.gbr.uplink;
qer->gbr.downlink = bearer->qos.gbr.downlink;
}
smf_epc_pfcp_send_bearer_modification_request(
bearer, OGS_PFCP_MODIFY_CREATE);
bearer, OGS_PFCP_MODIFY_ACTIVATE);
}
void smf_s5c_handle_update_bearer_response(
@ -425,7 +402,7 @@ void smf_s5c_handle_update_bearer_response(
bearer = smf_bearer_find_by_ebi(
sess, rsp->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
ogs_expect_or_return(bearer);
ogs_debug("[SMF] Update Bearer Response : SGW[0x%x] --> SMF[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid);
@ -523,7 +500,7 @@ void smf_s5c_handle_delete_bearer_response(
bearer = smf_bearer_find_by_ebi(
sess, rsp->bearer_contexts.eps_bearer_id.u8);
ogs_assert(bearer);
ogs_expect_or_return(bearer);
ogs_debug("[SMF] Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid);

View File

@ -25,6 +25,7 @@ ogs_pkbuf_t *upf_n4_build_session_establishment_response(uint8_t type,
{
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_establishment_response_t *rsp = NULL;
ogs_pkbuf_t *pkbuf = NULL;
int i = 0;
@ -59,18 +60,19 @@ ogs_pkbuf_t *upf_n4_build_session_establishment_response(uint8_t type,
rsp->up_f_seid.data = &f_seid;
rsp->up_f_seid.len = len;
ogs_pfcp_pdrbuf_init();
/* Created PDR */
for (i = 0; i < num_of_created_pdr; i++) {
ogs_pfcp_tlv_created_pdr_t *message = &rsp->created_pdr[i];
ogs_assert(message);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = created_pdr[i]->id;
ogs_pfcp_build_created_pdr(&rsp->created_pdr[i], i, created_pdr[i]);
}
pfcp_message.h.type = type;
return ogs_pfcp_build_msg(&pfcp_message);
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
ogs_pfcp_pdrbuf_clear();
return pkbuf;
}
ogs_pkbuf_t *upf_n4_build_session_modification_response(uint8_t type,
@ -78,6 +80,7 @@ ogs_pkbuf_t *upf_n4_build_session_modification_response(uint8_t type,
{
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_modification_response_t *rsp = NULL;
ogs_pkbuf_t *pkbuf = NULL;
int i = 0;
@ -90,18 +93,19 @@ ogs_pkbuf_t *upf_n4_build_session_modification_response(uint8_t type,
rsp->cause.presence = 1;
rsp->cause.u8 = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
ogs_pfcp_pdrbuf_init();
/* Created PDR */
for (i = 0; i < num_of_created_pdr; i++) {
ogs_pfcp_tlv_created_pdr_t *message = &rsp->created_pdr[i];
ogs_assert(message);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = created_pdr[i]->id;
ogs_pfcp_build_created_pdr(&rsp->created_pdr[i], i, created_pdr[i]);
}
pfcp_message.h.type = type;
return ogs_pfcp_build_msg(&pfcp_message);
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
ogs_pfcp_pdrbuf_clear();
return pkbuf;
}
ogs_pkbuf_t *upf_n4_build_session_deletion_response(uint8_t type,

View File

@ -117,8 +117,40 @@ void upf_n4_handle_session_establishment_request(
ogs_assert(pdr);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { /* Uplink */
if (pdr->f_teid_len)
if (pdr->f_teid_len) {
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
if (upf_self()->gtpu_sock)
addr = &upf_self()->gtpu_sock->local_addr;
if (upf_self()->gtpu_sock6)
addr6 = &upf_self()->gtpu_sock6->local_addr;
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = pdr->index;
}
}
ogs_pfcp_pdr_hash_set(pdr);
}
}
}
@ -269,8 +301,40 @@ void upf_n4_handle_session_modification_request(
ogs_assert(pdr);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { /* Uplink */
if (pdr->f_teid_len)
if (pdr->f_teid_len) {
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_gtpu_resource_find(
&ogs_pfcp_self()->gtpu_resource_list,
sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len);
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
if (upf_self()->gtpu_sock)
addr = &upf_self()->gtpu_sock->local_addr;
if (upf_self()->gtpu_sock6)
addr6 = &upf_self()->gtpu_sock6->local_addr;
ogs_assert(addr || addr6);
ogs_pfcp_sockaddr_to_f_teid(
addr, addr6, &pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = pdr->index;
}
}
ogs_pfcp_pdr_hash_set(pdr);
}
}
}