Set v4/v6 flags in local F-TEID (#1625)

This commit is contained in:
Sukchan Lee 2022-06-24 15:16:54 +09:00
parent 99fd6c449a
commit f4eddf91b5
12 changed files with 184 additions and 40 deletions

View File

@ -286,23 +286,29 @@ int ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
ogs_pfcp_f_teid_t *f_teid, int *len)
{
const int hdr_len = 5;
int v4, v6;
ogs_assert(info);
ogs_assert(f_teid);
v4 = info->v4 & f_teid->ipv4;
v6 = info->v6 & f_teid->ipv6;
ogs_assert(v4 || v6);
memset(f_teid, 0, sizeof *f_teid);
if (info->v4 && info->v6) {
if (v4 && v6) {
f_teid->ipv4 = 1;
f_teid->both.addr = info->addr;
f_teid->ipv6 = 1;
memcpy(f_teid->both.addr6, info->addr6, OGS_IPV6_LEN);
*len = OGS_IPV4V6_LEN + hdr_len;
} else if (info->v4) {
} else if (v4) {
f_teid->ipv4 = 1;
f_teid->ipv6 = 0;
f_teid->addr = info->addr;
*len = OGS_IPV4_LEN + hdr_len;
} else if (info->v6) {
} else if (v6) {
f_teid->ipv4 = 0;
f_teid->ipv6 = 1;
memcpy(f_teid->addr6, info->addr6, OGS_IPV6_LEN);

View File

@ -311,6 +311,20 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
return NULL;
}
if (message->pdi.local_f_teid.presence) {
ogs_pfcp_f_teid_t f_teid;
memcpy(&f_teid, message->pdi.local_f_teid.data,
message->pdi.local_f_teid.len);
if (f_teid.ipv4 == 0 && f_teid.ipv6 == 0) {
ogs_error("One of the IPv4 and IPv6 flags should be 1 "
"in the local F-TEID");
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT;
*offending_ie_value = OGS_PFCP_F_TEID_TYPE;
return NULL;
}
}
pdr->src_if = message->pdi.source_interface.u8;
ogs_pfcp_rule_remove_all(pdr);
@ -437,6 +451,7 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
if (message->pdi.local_f_teid.presence) {
pdr->f_teid_len = message->pdi.local_f_teid.len;
memcpy(&pdr->f_teid, message->pdi.local_f_teid.data, pdr->f_teid_len);
ogs_assert(pdr->f_teid.ipv4 || pdr->f_teid.ipv6);
pdr->f_teid.teid = be32toh(pdr->f_teid.teid);
}
@ -522,8 +537,21 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_created_pdr(ogs_pfcp_sess_t *sess,
}
if (message->local_f_teid.presence) {
ogs_pfcp_f_teid_t f_teid;
memcpy(&f_teid, message->local_f_teid.data, message->local_f_teid.len);
if (f_teid.ipv4 == 0 && f_teid.ipv6 == 0) {
ogs_error("One of the IPv4 and IPv6 flags should be 1 "
"in the local F-TEID");
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT;
*offending_ie_value = OGS_PFCP_F_TEID_TYPE;
return NULL;
}
pdr->f_teid_len = message->local_f_teid.len;
memcpy(&pdr->f_teid, message->local_f_teid.data, pdr->f_teid_len);
ogs_assert(pdr->f_teid.ipv4 || pdr->f_teid.ipv6);
pdr->f_teid.teid = be32toh(pdr->f_teid.teid);
}
@ -567,6 +595,20 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_update_pdr(ogs_pfcp_sess_t *sess,
return NULL;
}
if (message->pdi.local_f_teid.presence) {
ogs_pfcp_f_teid_t f_teid;
memcpy(&f_teid, message->pdi.local_f_teid.data,
message->pdi.local_f_teid.len);
if (f_teid.ipv4 == 0 && f_teid.ipv6 == 0) {
ogs_error("One of the IPv4 and IPv6 flags should be 1 "
"in the local F-TEID");
*cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT;
*offending_ie_value = OGS_PFCP_F_TEID_TYPE;
return NULL;
}
}
pdr->src_if = message->pdi.source_interface.u8;
ogs_pfcp_rule_remove_all(pdr);

View File

@ -721,6 +721,22 @@ sgwc_tunnel_t *sgwc_tunnel_add(
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
/* TS 129 244 V16.5.0 8.2.3
*
* 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 providing 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.
*/
pdr->f_teid.ipv4 = 1;
pdr->f_teid.ipv6 = 1;
pdr->f_teid.ch = 1;
pdr->f_teid_len = 1;
} else {

View File

@ -120,6 +120,9 @@ void sgwu_sxa_handle_session_establishment_request(
&ogs_gtp_self()->gtpu_resource_list,
pdr->apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
@ -130,10 +133,15 @@ void sgwu_sxa_handle_session_establishment_request(
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
ogs_gtp_self()->gtpu_addr,
ogs_gtp_self()->gtpu_addr6,
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}
@ -327,6 +335,9 @@ void sgwu_sxa_handle_session_modification_request(
&ogs_gtp_self()->gtpu_resource_list,
pdr->apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
@ -337,10 +348,15 @@ void sgwu_sxa_handle_session_modification_request(
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
ogs_gtp_self()->gtpu_addr,
ogs_gtp_self()->gtpu_addr6,
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}

View File

@ -168,6 +168,22 @@ void smf_bearer_binding(smf_sess_t *sess)
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
/* TS 129 244 V16.5.0 8.2.3
*
* 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 providing 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.
*/
ul_pdr->f_teid.ipv4 = 1;
ul_pdr->f_teid.ipv6 = 1;
ul_pdr->f_teid.ch = 1;
ul_pdr->f_teid_len = 1;
} else {
@ -490,6 +506,22 @@ void smf_qos_flow_binding(smf_sess_t *sess)
/* Set UPF-N3 TEID & ADDR to the UL PDR */
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
/* TS 129 244 V16.5.0 8.2.3
*
* 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 providing 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.
*/
ul_pdr->f_teid.ipv4 = 1;
ul_pdr->f_teid.ipv6 = 1;
ul_pdr->f_teid.ch = 1;
ul_pdr->f_teid.chid = 1;
ul_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;

View File

@ -1957,6 +1957,22 @@ void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess)
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
/* TS 129 244 V16.5.0 8.2.3
*
* 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 providing 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.
*/
pdr->f_teid.ipv4 = 1;
pdr->f_teid.ipv6 = 1;
pdr->f_teid.ch = 1;
pdr->f_teid.chid = 1;
pdr->f_teid.choose_id = OGS_PFCP_INDIRECT_DATA_FORWARDING_CHOOSE_ID;

View File

@ -168,7 +168,7 @@ ogs_pkbuf_t *smf_gn_build_create_pdp_context_response(
/* End User Address */
rv = ogs_gtp2_paa_to_ip(&sess->session.paa, &ip_eua);
rv = ogs_gtp1_ip_to_eua(sess->session.paa.session_type, &ip_eua, &eua,
rv = ogs_gtp1_ip_to_eua(sess->session.session_type, &ip_eua, &eua,
&eua_len);
rsp->end_user_address.presence = 1;
rsp->end_user_address.data = &eua;

View File

@ -145,7 +145,7 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess)
/* PDU Address */
pdu_session_establishment_accept->presencemask |=
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_PDU_ADDRESS_PRESENT;
pdu_address->pdn_type = sess->session.paa.session_type;
pdu_address->pdn_type = sess->session.session_type;
if (pdu_address->pdn_type == OGS_PDU_SESSION_TYPE_IPV4) {
pdu_address->addr = sess->session.paa.addr;

View File

@ -170,14 +170,20 @@ uint32_t smf_gx_handle_cca_initial_request(
/* Set F-TEID */
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
ul_pdr->f_teid.ipv4 = 1;
ul_pdr->f_teid.ipv6 = 1;
ul_pdr->f_teid.ch = 1;
ul_pdr->f_teid.chid = 1;
ul_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;
ul_pdr->f_teid_len = 2;
cp2up_pdr->f_teid.ipv4 = 1;
cp2up_pdr->f_teid.ipv6 = 1;
cp2up_pdr->f_teid.ch = 1;
cp2up_pdr->f_teid_len = 1;
up2cp_pdr->f_teid.ipv4 = 1;
up2cp_pdr->f_teid.ipv6 = 1;
up2cp_pdr->f_teid.ch = 1;
up2cp_pdr->f_teid.chid = 1;
up2cp_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;

View File

@ -100,7 +100,7 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
/* PDN Type */
req->pdn_type.presence = 1;
req->pdn_type.u8 = sess->session.paa.session_type;
req->pdn_type.u8 = sess->session.session_type;
pfcp_message.h.type = type;
pkbuf = ogs_pfcp_build_msg(&pfcp_message);

View File

@ -507,44 +507,38 @@ bool smf_npcf_smpolicycontrol_handle_create(
/* Set UPF-N3 TEID & ADDR to the Default UL PDR */
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
/* TS 129 244 V16.5.0 8.2.3
*
* 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 providing 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.
*/
ul_pdr->f_teid.ipv4 = 1;
ul_pdr->f_teid.ipv6 = 1;
ul_pdr->f_teid.ch = 1;
ul_pdr->f_teid.chid = 1;
ul_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;
ul_pdr->f_teid_len = 2;
/* TS 129 244 V16.5.0 8.2.3
*
* 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 providing 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.
*/
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ul_pdr->f_teid.ipv4 = 1;
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
ul_pdr->f_teid.ipv6 = 1;
cp2up_pdr->f_teid.ipv4 = 1;
cp2up_pdr->f_teid.ipv6 = 1;
cp2up_pdr->f_teid.ch = 1;
cp2up_pdr->f_teid_len = 1;
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
cp2up_pdr->f_teid.ipv4 = 1;
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
cp2up_pdr->f_teid.ipv6 = 1;
up2cp_pdr->f_teid.ipv4 = 1;
up2cp_pdr->f_teid.ipv6 = 1;
up2cp_pdr->f_teid.ch = 1;
up2cp_pdr->f_teid.chid = 1;
up2cp_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;
up2cp_pdr->f_teid_len = 2;
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
up2cp_pdr->f_teid.ipv4 = 1;
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
up2cp_pdr->f_teid.ipv6 = 1;
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(

View File

@ -157,6 +157,9 @@ void upf_n4_handle_session_establishment_request(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
@ -167,10 +170,15 @@ void upf_n4_handle_session_establishment_request(
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
ogs_gtp_self()->gtpu_addr,
ogs_gtp_self()->gtpu_addr6,
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}
@ -392,6 +400,9 @@ void upf_n4_handle_session_modification_request(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
@ -402,10 +413,15 @@ void upf_n4_handle_session_modification_request(
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
ogs_gtp_self()->gtpu_addr,
ogs_gtp_self()->gtpu_addr6,
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}