[SMF/UPF] Clarify FALLBACK SUBNET [#1128]

This commit is contained in:
Sukchan Lee 2021-08-14 16:52:53 +09:00
parent e5594a57b9
commit 3564fe5c8c
16 changed files with 137 additions and 37 deletions

View File

@ -122,6 +122,7 @@ logger:
#
#
# o Specific DNN/APN(e.g 'ims') uses 10.46.0.1/16, 2001:230:babe::1/48
# ; If the UE has unknown DNN/APN(not internet/ims), SMF/UPF will crash.
#
# subnet:
# - addr: 10.45.0.1/16
@ -133,6 +134,16 @@ logger:
# - addr: 2001:230:babe::1/48
# dnn: ims
#
# o Specific DNN/APN with the FALLBACK SUBNET(10.47.0.1/16)
# ; Note that put the FALLBACK SUBNET last to avoid SMF/UPF crash.
#
# subnet:
# - addr: 10.45.0.1/16
# dnn: internet
# - addr: 10.46.0.1/16
# dnn: ims
# - addr: 10.50.0.1/16 ## FALLBACK SUBNET
#
# o Pool Range Sample
# subnet:
# - addr: 10.45.0.1/24

View File

@ -107,6 +107,8 @@ logger:
# $ sudo ip addr add 2001:230:cafe::1/48 dev ogstun
# $ sudo ip addr add 2001:230:babe::1/48 dev ogstun
#
# ; If the UE has unknown DNN/APN(not internet/ims), SMF/UPF will crash.
#
# subnet:
# - addr: 10.45.0.1/16
# dnn: internet
@ -117,6 +119,16 @@ logger:
# - addr: 2001:230:babe::1/48
# dnn: ims
#
# o Specific DNN/APN with the FALLBACK SUBNET(10.47.0.1/16)
# ; Note that put the FALLBACK SUBNET last to avoid SMF/UPF crash.
#
# subnet:
# - addr: 10.45.0.1/16
# dnn: internet
# - addr: 10.46.0.1/16
# dnn: ims
# - addr: 10.50.0.1/16 ## FALLBACK SUBNET
#
# o Multiple Devices (default: ogstun)
# $ sudo ip addr add 10.45.0.1/16 dev ogstun
# $ sudo ip addr add 2001:230:cafe::1/48 dev ogstun2

View File

@ -1572,7 +1572,7 @@ int ogs_pfcp_ue_pool_generate(void)
}
ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
int family, const char *dnn, uint8_t *addr)
uint8_t *cause_value, int family, const char *dnn, uint8_t *addr)
{
ogs_pfcp_subnet_t *subnet = NULL;
ogs_pfcp_ue_ip_t *ue_ip = NULL;
@ -1587,6 +1587,7 @@ ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
maxbytes = 16;
} else {
ogs_error("Invalid family[%d]", family);
ogs_assert_if_reached();
return NULL;
}
@ -1598,27 +1599,36 @@ ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
if (subnet == NULL) {
ogs_error("CHECK CONFIGURATION: Cannot find subnet [family:%d, dnn:%s]",
family, dnn ? dnn : "No DNN");
ogs_error("smf");
ogs_error("Please add FALLBACK subnet as below.");
ogs_error(" subnet:");
if (family == AF_INET)
ogs_error(" - addr: 10.45.0.1/16");
ogs_error(" - addr: 10.50.0.1/16");
else if (family == AF_INET6)
ogs_error(" - addr: 2001:230:cafe::1/48");
ogs_error(" - addr: 2001:230:abcd::1/48");
*cause_value = OGS_PFCP_CAUSE_SYSTEM_FAILURE;
return NULL;
}
/* if assigning a static IP, do so. If not, assign dynamically! */
if (memcmp(addr, zero, maxbytes) != 0) {
ue_ip = ogs_calloc(1, sizeof(ogs_pfcp_ue_ip_t));
ogs_expect_or_return_val(ue_ip, NULL);
if (!ue_ip) {
ogs_error("All dynamic addresses are occupied");
*cause_value = OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED;
return NULL;
}
ue_ip->subnet = subnet;
ue_ip->static_ip = true;
memcpy(ue_ip->addr, addr, maxbytes);
} else {
ogs_pool_alloc(&subnet->pool, &ue_ip);
ogs_expect(ue_ip);
if (!ue_ip) {
ogs_error("No resources avaiable");
*cause_value = OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE;
return NULL;
}
}
return ue_ip;

View File

@ -421,7 +421,7 @@ void ogs_pfcp_rule_remove_all(ogs_pfcp_pdr_t *pdr);
int ogs_pfcp_ue_pool_generate(void);
ogs_pfcp_ue_ip_t *ogs_pfcp_ue_ip_alloc(
int family, const char *dnn, uint8_t *addr);
uint8_t *cause_value, int family, const char *dnn, uint8_t *addr);
void ogs_pfcp_ue_ip_free(ogs_pfcp_ue_ip_t *ip);
ogs_pfcp_dev_t *ogs_pfcp_dev_add(const char *ifname);

View File

@ -37,6 +37,7 @@ typedef uint32_t ogs_pfcp_qer_id_t;
typedef uint8_t ogs_pfcp_bar_id_t;
#define OGS_PFCP_CAUSE_REQUEST_ACCEPTED 1
#define OGS_PFCP_CAUSE_MORE_USAGE_REPORT_TO_SEND 2
#define OGS_PFCP_CAUSE_REQUEST_REJECTED 64
#define OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND 65
#define OGS_PFCP_CAUSE_MANDATORY_IE_MISSING 66
@ -51,6 +52,8 @@ typedef uint8_t ogs_pfcp_bar_id_t;
#define OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE 75
#define OGS_PFCP_CAUSE_SERVICE_NOT_SUPPORTED 76
#define OGS_PFCP_CAUSE_SYSTEM_FAILURE 77
#define OGS_PFCP_CAUSE_REDIRECTION_REQUESTED 78
#define OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED 79
const char *ogs_pfcp_cause_get_name(uint8_t cause);

View File

@ -2698,6 +2698,12 @@ mme_sess_t *mme_sess_next(mme_sess_t *sess)
return ogs_list_next(sess);
}
bool mme_ue_in_attach(mme_ue_t *mme_ue)
{
ogs_assert(mme_ue);
return (ogs_list_count(&mme_ue->sess_list) <= 1);
}
bool mme_sess_in_attach(mme_sess_t *sess)
{
mme_ue_t *mme_ue = NULL;
@ -2706,7 +2712,7 @@ bool mme_sess_in_attach(mme_sess_t *sess)
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
return (ogs_list_count(&mme_ue->sess_list) <= 1);
return mme_ue_in_attach(mme_ue);
}
unsigned int mme_sess_count(mme_ue_t *mme_ue)

View File

@ -778,7 +778,9 @@ mme_sess_t *mme_sess_first(mme_ue_t *mme_ue);
mme_sess_t *mme_sess_next(mme_sess_t *sess);
unsigned int mme_sess_count(mme_ue_t *mme_ue);
#define UE_CONTEXT_IN_ATTACH(__mME) mme_ue_in_attach(__mME)
#define SESSION_CONTEXT_IN_ATTACH(__sESS) mme_sess_in_attach(__sESS)
bool mme_ue_in_attach(mme_ue_t *mme_ue);
bool mme_sess_in_attach(mme_sess_t *sess);
mme_bearer_t *mme_bearer_add(mme_sess_t *sess);

View File

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

View File

@ -1184,11 +1184,13 @@ smf_sess_t *smf_sess_add_by_sbi_message(ogs_sbi_message_t *message)
return sess;
}
void smf_sess_set_ue_ip(smf_sess_t *sess)
uint8_t smf_sess_set_ue_ip(smf_sess_t *sess)
{
ogs_pfcp_subnet_t *subnet6 = NULL;
smf_ue_t *smf_ue = NULL;
uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
@ -1235,16 +1237,24 @@ void smf_sess_set_ue_ip(smf_sess_t *sess)
}
if (sess->session.session_type == OGS_PDU_SESSION_TYPE_IPV4) {
sess->ipv4 = ogs_pfcp_ue_ip_alloc(AF_INET,
sess->ipv4 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET,
sess->session.name, (uint8_t *)&sess->session.ue_ip.addr);
ogs_assert(sess->ipv4);
if (!sess->ipv4) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
return cause_value;
}
sess->session.paa.addr = sess->ipv4->addr[0];
ogs_hash_set(smf_self()->ipv4_hash,
sess->ipv4->addr, OGS_IPV4_LEN, sess);
} else if (sess->session.session_type == OGS_PDU_SESSION_TYPE_IPV6) {
sess->ipv6 = ogs_pfcp_ue_ip_alloc(
AF_INET6, sess->session.name, sess->session.ue_ip.addr6);
ogs_assert(sess->ipv6);
sess->ipv6 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET6,
sess->session.name, sess->session.ue_ip.addr6);
if (!sess->ipv6) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
return cause_value;
}
subnet6 = sess->ipv6->subnet;
ogs_assert(subnet6);
@ -1254,12 +1264,26 @@ void smf_sess_set_ue_ip(smf_sess_t *sess)
ogs_hash_set(smf_self()->ipv6_hash,
sess->ipv6->addr, OGS_IPV6_DEFAULT_PREFIX_LEN >> 3, sess);
} else if (sess->session.session_type == OGS_PDU_SESSION_TYPE_IPV4V6) {
sess->ipv4 = ogs_pfcp_ue_ip_alloc(AF_INET,
sess->ipv4 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET,
sess->session.name, (uint8_t *)&sess->session.ue_ip.addr);
ogs_assert(sess->ipv4);
sess->ipv6 = ogs_pfcp_ue_ip_alloc(
AF_INET6, sess->session.name, sess->session.ue_ip.addr6);
ogs_assert(sess->ipv6);
if (!sess->ipv4) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
return cause_value;
}
sess->ipv6 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET6,
sess->session.name, sess->session.ue_ip.addr6);
if (!sess->ipv6) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
if (sess->ipv4) {
ogs_hash_set(smf_self()->ipv4_hash,
sess->ipv4->addr, OGS_IPV4_LEN, NULL);
ogs_pfcp_ue_ip_free(sess->ipv4);
sess->ipv4 = NULL;
}
return cause_value;
}
subnet6 = sess->ipv6->subnet;
ogs_assert(subnet6);
@ -1276,6 +1300,8 @@ void smf_sess_set_ue_ip(smf_sess_t *sess)
sess->session.session_type);
ogs_assert_if_reached();
}
return cause_value;
}
void smf_sess_set_paging_n1n2message_location(

View File

@ -361,7 +361,7 @@ smf_sess_t *smf_sess_add_by_sbi_message(ogs_sbi_message_t *message);
smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi);
void smf_sess_select_upf(smf_sess_t *sess);
void smf_sess_set_ue_ip(smf_sess_t *sess);
uint8_t smf_sess_set_ue_ip(smf_sess_t *sess);
void smf_sess_set_paging_n1n2message_location(
smf_sess_t *sess, char *n1n2message_location);

View File

@ -58,6 +58,8 @@ static uint8_t gtp_cause_from_pfcp(uint8_t pfcp_cause)
return OGS_GTP_CAUSE_SERVICE_NOT_SUPPORTED;
case OGS_PFCP_CAUSE_SYSTEM_FAILURE:
return OGS_GTP_CAUSE_SYSTEM_FAILURE;
case OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED:
return OGS_GTP_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED;
default:
return OGS_GTP_CAUSE_SYSTEM_FAILURE;
}

View File

@ -244,7 +244,7 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream,
}
/* Set UE IP Address to the Default DL PDR */
smf_sess_set_ue_ip(sess);
ogs_assert(OGS_PFCP_CAUSE_REQUEST_ACCEPTED == smf_sess_set_ue_ip(sess));
/*********************************************************************
* Send HTTP_STATUS_CREATED(/nsmf-pdusession/v1/sm-context) to the AMF

View File

@ -216,7 +216,7 @@ void smf_s5c_handle_create_session_request(
rv = ogs_gtp_paa_to_ip(paa, &sess->session.ue_ip);
ogs_assert(rv == OGS_OK);
smf_sess_set_ue_ip(sess);
ogs_assert(OGS_PFCP_CAUSE_REQUEST_ACCEPTED == smf_sess_set_ue_ip(sess));
ogs_info("UE IMSI[%s] APN[%s] IPv4[%s] IPv6[%s]",
smf_ue->imsi_bcd,

View File

@ -256,13 +256,15 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
return sess;
}
void upf_sess_set_ue_ip(upf_sess_t *sess,
uint8_t upf_sess_set_ue_ip(upf_sess_t *sess,
uint8_t session_type, ogs_pfcp_pdr_t *pdr)
{
ogs_pfcp_ue_ip_addr_t *ue_ip = NULL;
char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN];
uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
ogs_assert(sess);
ogs_assert(session_type);
ogs_assert(pdr);
@ -284,9 +286,13 @@ void upf_sess_set_ue_ip(upf_sess_t *sess,
/* Set PDN-Type and UE IP Address */
if (session_type == OGS_PDU_SESSION_TYPE_IPV4) {
if (ue_ip->ipv4 || pdr->dnn) {
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
AF_INET, pdr->dnn, (uint8_t *)&(ue_ip->addr));
ogs_assert(sess->ipv4);
sess->ipv4 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET,
pdr->dnn, (uint8_t *)&(ue_ip->addr));
if (!sess->ipv4) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
return cause_value;
}
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, sess);
} else {
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
@ -295,8 +301,13 @@ void upf_sess_set_ue_ip(upf_sess_t *sess,
}
} else if (session_type == OGS_PDU_SESSION_TYPE_IPV6) {
if (ue_ip->ipv6 || pdr->dnn) {
sess->ipv6 = ogs_pfcp_ue_ip_alloc(AF_INET6, pdr->dnn, ue_ip->addr6);
ogs_assert(sess->ipv6);
sess->ipv6 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET6,
pdr->dnn, ue_ip->addr6);
if (!sess->ipv6) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
return cause_value;
}
ogs_hash_set(self.ipv6_hash, sess->ipv6->addr,
OGS_IPV6_DEFAULT_PREFIX_LEN >> 3, sess);
} else {
@ -306,9 +317,13 @@ void upf_sess_set_ue_ip(upf_sess_t *sess,
}
} else if (session_type == OGS_PDU_SESSION_TYPE_IPV4V6) {
if (ue_ip->ipv4 || pdr->dnn) {
sess->ipv4 = ogs_pfcp_ue_ip_alloc(
AF_INET, pdr->dnn, (uint8_t *)&(ue_ip->both.addr));
ogs_assert(sess->ipv4);
sess->ipv4 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET,
pdr->dnn, (uint8_t *)&(ue_ip->both.addr));
if (!sess->ipv4) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
return cause_value;
}
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, sess);
} else {
ogs_warn("Cannot support PDN-Type[%d], [IPv4:%d IPv6:%d DNN:%s]",
@ -317,9 +332,19 @@ void upf_sess_set_ue_ip(upf_sess_t *sess,
}
if (ue_ip->ipv6 || pdr->dnn) {
sess->ipv6 = ogs_pfcp_ue_ip_alloc(
AF_INET6, pdr->dnn, ue_ip->both.addr6);
ogs_assert(sess->ipv6);
sess->ipv6 = ogs_pfcp_ue_ip_alloc(&cause_value, AF_INET6,
pdr->dnn, ue_ip->both.addr6);
if (!sess->ipv6) {
ogs_error("ogs_pfcp_ue_ip_alloc() failed[%d]", cause_value);
ogs_assert(cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED);
if (sess->ipv4) {
ogs_hash_set(self.ipv4_hash,
sess->ipv4->addr, OGS_IPV4_LEN, NULL);
ogs_pfcp_ue_ip_free(sess->ipv4);
sess->ipv4 = NULL;
}
return cause_value;
}
ogs_hash_set(self.ipv6_hash, sess->ipv6->addr,
OGS_IPV6_DEFAULT_PREFIX_LEN >> 3, sess);
} else {
@ -339,4 +364,6 @@ void upf_sess_set_ue_ip(upf_sess_t *sess,
pdr->dnn, session_type,
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
return cause_value;
}

View File

@ -88,7 +88,7 @@ upf_sess_t *upf_sess_find_by_up_seid(uint64_t seid);
upf_sess_t *upf_sess_find_by_ipv4(uint32_t addr);
upf_sess_t *upf_sess_find_by_ipv6(uint32_t *addr6);
void upf_sess_set_ue_ip(upf_sess_t *sess,
uint8_t upf_sess_set_ue_ip(upf_sess_t *sess,
uint8_t session_type, ogs_pfcp_pdr_t *pdr);
#ifdef __cplusplus

View File

@ -93,7 +93,8 @@ void upf_n4_handle_session_establishment_request(
/* Setup UE IP address */
if (req->pdn_type.presence && pdr->ue_ip_addr_len) {
upf_sess_set_ue_ip(sess, req->pdn_type.u8, pdr);
ogs_assert(OGS_PFCP_CAUSE_REQUEST_ACCEPTED ==
upf_sess_set_ue_ip(sess, req->pdn_type.u8, pdr));
}
/* Setup UPF-N3-TEID & QFI Hash */