open5gs/src/smf/n4-handler.c

1279 lines
46 KiB
C
Raw Normal View History

2020-04-26 19:36:05 +00:00
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "context.h"
#include "timer.h"
#include "s5c-build.h"
2020-04-26 19:36:05 +00:00
#include "pfcp-path.h"
#include "gtp-path.h"
#include "n4-handler.h"
2021-01-01 02:07:08 +00:00
#include "binding.h"
2020-06-17 05:22:28 +00:00
#include "sbi-path.h"
2021-01-01 02:07:08 +00:00
#include "ngap-path.h"
#include "fd-path.h"
2020-04-26 19:36:05 +00:00
uint8_t gtp_cause_from_pfcp(uint8_t pfcp_cause, uint8_t gtp_version)
2020-04-26 19:36:05 +00:00
{
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
switch (gtp_version) {
case 1:
switch (pfcp_cause) {
case OGS_PFCP_CAUSE_REQUEST_ACCEPTED:
return OGS_GTP1_CAUSE_REQUEST_ACCEPTED;
case OGS_PFCP_CAUSE_REQUEST_REJECTED:
return OGS_GTP1_CAUSE_REJ_MS_NOT_GPRS_RESPONDING;
case OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND:
return OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND;
case OGS_PFCP_CAUSE_MANDATORY_IE_MISSING:
case OGS_PFCP_CAUSE_CONDITIONAL_IE_MISSING:
return OGS_GTP1_CAUSE_MANDATORY_IE_MISSING;
case OGS_PFCP_CAUSE_INVALID_LENGTH:
return OGS_GTP1_CAUSE_INVALID_MESSAGE_FORMAT;
case OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT:
return OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT;
case OGS_PFCP_CAUSE_INVALID_FORWARDING_POLICY:
case OGS_PFCP_CAUSE_INVALID_F_TEID_ALLOCATION_OPTION:
return OGS_GTP1_CAUSE_INVALID_MESSAGE_FORMAT;
case OGS_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOCIATION:
return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE;
case OGS_PFCP_CAUSE_RULE_CREATION_MODIFICATION_FAILURE:
return OGS_GTP1_CAUSE_SEMANTIC_ERR_TFT_OPERATION;
case OGS_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION:
return OGS_GTP1_CAUSE_APN_CONGESTION;
case OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE:
return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE;
case OGS_PFCP_CAUSE_SERVICE_NOT_SUPPORTED:
return OGS_GTP1_CAUSE_SERVICE_NOT_SUPPORTED;
case OGS_PFCP_CAUSE_SYSTEM_FAILURE:
return OGS_GTP1_CAUSE_SYSTEM_FAILURE;
case OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED:
return OGS_GTP1_CAUSE_ALL_DYNAMIC_PDP_ADDRS_OCCUPIED;
default:
return OGS_GTP1_CAUSE_SYSTEM_FAILURE;
}
break;
case 2:
switch (pfcp_cause) {
case OGS_PFCP_CAUSE_REQUEST_ACCEPTED:
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_REQUEST_REJECTED:
return OGS_GTP2_CAUSE_REQUEST_REJECTED_REASON_NOT_SPECIFIED;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND:
return OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_MANDATORY_IE_MISSING:
return OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_CONDITIONAL_IE_MISSING:
return OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_INVALID_LENGTH:
return OGS_GTP2_CAUSE_INVALID_LENGTH;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT:
return OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_INVALID_FORWARDING_POLICY:
case OGS_PFCP_CAUSE_INVALID_F_TEID_ALLOCATION_OPTION:
return OGS_GTP2_CAUSE_INVALID_MESSAGE_FORMAT;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOCIATION:
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_RULE_CREATION_MODIFICATION_FAILURE:
return OGS_GTP2_CAUSE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION:
return OGS_GTP2_CAUSE_GTP_C_ENTITY_CONGESTION;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE:
return OGS_GTP2_CAUSE_NO_RESOURCES_AVAILABLE;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_SERVICE_NOT_SUPPORTED:
return OGS_GTP2_CAUSE_SERVICE_NOT_SUPPORTED;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_SYSTEM_FAILURE:
return OGS_GTP2_CAUSE_SYSTEM_FAILURE;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
case OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED:
return OGS_GTP2_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
default:
return OGS_GTP2_CAUSE_SYSTEM_FAILURE;
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
}
break;
2020-04-26 19:36:05 +00:00
}
return OGS_GTP2_CAUSE_SYSTEM_FAILURE;
2020-04-26 19:36:05 +00:00
}
2021-01-18 16:48:35 +00:00
2020-07-04 03:14:48 +00:00
static int sbi_status_from_pfcp(uint8_t pfcp_cause)
{
switch (pfcp_cause) {
case OGS_PFCP_CAUSE_REQUEST_ACCEPTED:
return OGS_SBI_HTTP_STATUS_OK;
case OGS_PFCP_CAUSE_REQUEST_REJECTED:
return OGS_SBI_HTTP_STATUS_FORBIDDEN;
case OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND:
return OGS_SBI_HTTP_STATUS_NOT_FOUND;
case OGS_PFCP_CAUSE_MANDATORY_IE_MISSING:
case OGS_PFCP_CAUSE_CONDITIONAL_IE_MISSING:
case OGS_PFCP_CAUSE_INVALID_LENGTH:
case OGS_PFCP_CAUSE_MANDATORY_IE_INCORRECT:
case OGS_PFCP_CAUSE_INVALID_FORWARDING_POLICY:
case OGS_PFCP_CAUSE_INVALID_F_TEID_ALLOCATION_OPTION:
case OGS_PFCP_CAUSE_RULE_CREATION_MODIFICATION_FAILURE:
case OGS_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION:
case OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE:
return OGS_SBI_HTTP_STATUS_BAD_REQUEST;
case OGS_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOCIATION:
return OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT;
case OGS_PFCP_CAUSE_SERVICE_NOT_SUPPORTED:
return OGS_SBI_HTTP_STATUS_SERVICE_UNAVAILABLE;
case OGS_PFCP_CAUSE_SYSTEM_FAILURE:
return OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR;
default:
return OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR;
}
return OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR;
}
2020-04-26 19:36:05 +00:00
2022-05-14 21:27:54 +00:00
/* Returns OGS_PFCP_CAUSE_REQUEST_ACCEPTED on success,
* other cause value on failure */
uint8_t smf_5gc_n4_handle_session_establishment_response(
2020-06-17 05:22:28 +00:00
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_establishment_response_t *rsp)
{
int i;
ogs_sbi_stream_t *stream = NULL;
uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
2020-06-17 05:22:28 +00:00
ogs_pfcp_f_seid_t *up_f_seid = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_assert(sess);
2020-06-17 05:22:28 +00:00
ogs_assert(xact);
ogs_assert(rsp);
ogs_debug("Session Establishment Response [5gc]");
stream = xact->assoc_stream;
ogs_assert(stream);
2020-06-17 05:22:28 +00:00
ogs_pfcp_xact_commit(xact);
if (rsp->up_f_seid.presence == 0) {
ogs_error("No UP F-SEID");
cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
2020-06-17 05:22:28 +00:00
}
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
2020-07-04 03:14:48 +00:00
ogs_error("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
cause_value = rsp->cause.u8;
2020-06-17 05:22:28 +00:00
}
} else {
ogs_error("No Cause");
cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
2020-06-17 05:22:28 +00:00
}
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
return cause_value;
2020-07-04 03:14:48 +00:00
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&cause_value, &offending_ie_value);
if (!pdr)
break;
}
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
2021-03-15 01:01:55 +00:00
far = pdr->far;
ogs_assert(far);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) {
if (far->dst_if == OGS_PFCP_INTERFACE_CP_FUNCTION)
ogs_pfcp_far_teid_hash_set(far);
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);
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_OK ==
ogs_pfcp_f_teid_to_sockaddr(
2021-03-15 01:01:55 +00:00
&pdr->f_teid, pdr->f_teid_len,
2021-06-06 13:35:46 +00:00
&sess->upf_n3_addr, &sess->upf_n3_addr6));
2021-03-15 01:01:55 +00:00
sess->upf_n3_teid = pdr->f_teid.teid;
}
} else if (pdr->src_if == OGS_PFCP_INTERFACE_CP_FUNCTION) {
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_ERROR != ogs_pfcp_setup_pdr_gtpu_node(pdr));
}
}
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_error("PFCP Cause [%d] : Not Accepted", cause_value);
return cause_value;
}
if (sess->upf_n3_addr == NULL && sess->upf_n3_addr6 == NULL) {
ogs_error("No UP F-TEID");
return OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
}
2020-06-17 05:22:28 +00:00
/* UP F-SEID */
up_f_seid = rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->upf_n4_seid = be64toh(up_f_seid->seid);
return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
2020-06-17 05:22:28 +00:00
}
void smf_5gc_n4_handle_session_modification_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_modification_response_t *rsp)
{
2020-07-04 03:14:48 +00:00
int status = 0;
uint64_t flags = 0;
ogs_sbi_stream_t *stream = NULL;
2021-01-01 02:07:08 +00:00
smf_bearer_t *qos_flow = NULL;
2020-06-17 05:22:28 +00:00
OGS_LIST(pdr_to_create_list);
ogs_debug("Session Modification Response [5gc]");
2020-06-17 05:22:28 +00:00
ogs_assert(xact);
ogs_assert(rsp);
flags = xact->modify_flags;
ogs_assert(flags);
2020-06-17 05:22:28 +00:00
2021-01-01 02:07:08 +00:00
/* 'stream' could be NULL in smf_qos_flow_binding() */
stream = xact->assoc_stream;
if (flags & OGS_PFCP_MODIFY_SESSION) {
/* If smf_5gc_pfcp_send_pdr_modification_request() is called */
} else {
/* If smf_5gc_pfcp_send_qos_flow_modification_request() is called */
qos_flow = xact->data;
ogs_assert(qos_flow);
}
2021-01-01 02:07:08 +00:00
ogs_list_copy(&pdr_to_create_list, &xact->pdr_to_create_list);
2020-06-17 05:22:28 +00:00
ogs_pfcp_xact_commit(xact);
2020-07-04 03:14:48 +00:00
status = OGS_SBI_HTTP_STATUS_OK;
if (!sess) {
ogs_warn("No Context");
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
}
2020-06-17 05:22:28 +00:00
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
2020-07-04 03:14:48 +00:00
ogs_warn("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
status = sbi_status_from_pfcp(rsp->cause.u8);
2020-06-17 05:22:28 +00:00
}
} else {
ogs_error("No Cause");
2020-07-04 03:14:48 +00:00
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_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_assert(sess);
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
}
ogs_list_for_each_entry(&pdr_to_create_list, pdr, to_create_node) {
2021-03-15 01:01:55 +00:00
far = pdr->far;
ogs_assert(far);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) {
if (far->dst_if == OGS_PFCP_INTERFACE_CP_FUNCTION)
ogs_pfcp_far_teid_hash_set(far);
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
if (sess->upf_n3_addr)
ogs_freeaddrinfo(sess->upf_n3_addr);
if (sess->upf_n3_addr6)
ogs_freeaddrinfo(sess->upf_n3_addr6);
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_OK ==
ogs_pfcp_f_teid_to_sockaddr(
2021-03-15 01:01:55 +00:00
&pdr->f_teid, pdr->f_teid_len,
2021-06-06 13:35:46 +00:00
&sess->upf_n3_addr, &sess->upf_n3_addr6));
2021-03-15 01:01:55 +00:00
sess->upf_n3_teid = pdr->f_teid.teid;
} else if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
if (sess->handover.upf_dl_addr)
ogs_freeaddrinfo(sess->handover.upf_dl_addr);
if (sess->handover.upf_dl_addr6)
ogs_freeaddrinfo(sess->handover.upf_dl_addr6);
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_OK ==
ogs_pfcp_f_teid_to_sockaddr(
2021-03-15 01:01:55 +00:00
&pdr->f_teid, pdr->f_teid_len,
&sess->handover.upf_dl_addr,
2021-06-06 13:35:46 +00:00
&sess->handover.upf_dl_addr6));
2021-03-15 01:01:55 +00:00
sess->handover.upf_dl_teid = pdr->f_teid.teid;
}
}
2021-03-15 01:01:55 +00:00
} else if (pdr->src_if == OGS_PFCP_INTERFACE_CP_FUNCTION) {
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_ERROR != ogs_pfcp_setup_pdr_gtpu_node(pdr));
}
}
status = sbi_status_from_pfcp(pfcp_cause_value);
}
2020-07-04 03:14:48 +00:00
if (status != OGS_SBI_HTTP_STATUS_OK) {
char *strerror = ogs_msprintf(
"PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
2021-01-01 02:07:08 +00:00
if (stream)
smf_sbi_send_sm_context_update_error(
stream, status, strerror, NULL, NULL, NULL);
ogs_error("%s", strerror);
2020-07-04 03:14:48 +00:00
ogs_free(strerror);
2020-06-17 05:22:28 +00:00
return;
}
2020-07-04 03:14:48 +00:00
ogs_assert(sess);
if (sess->upf_n3_addr == NULL && sess->upf_n3_addr6 == NULL) {
2021-01-01 02:07:08 +00:00
if (stream)
smf_sbi_send_sm_context_update_error(
stream, status, "No UP F_TEID", NULL, NULL, NULL);
return;
}
2020-08-13 00:31:22 +00:00
if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
2021-01-28 19:23:54 +00:00
if (flags & OGS_PFCP_MODIFY_XN_HANDOVER) {
2021-01-03 05:50:59 +00:00
ogs_pkbuf_t *n2smbuf =
ngap_build_path_switch_request_ack_transfer(sess);
ogs_assert(n2smbuf);
2021-01-18 16:48:35 +00:00
smf_sbi_send_sm_context_updated_data_n2smbuf(sess, stream,
2021-01-03 05:50:59 +00:00
OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ_ACK, n2smbuf);
2021-01-28 19:23:54 +00:00
} else if (flags & OGS_PFCP_MODIFY_N2_HANDOVER) {
if (smf_sess_have_indirect_data_forwarding(sess) == true) {
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_pdr_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_REMOVE,
ogs_app()->time.handover.duration));
}
2021-01-28 19:23:54 +00:00
smf_sbi_send_sm_context_updated_data_ho_state(
sess, stream, OpenAPI_ho_state_COMPLETED);
2021-01-18 16:48:35 +00:00
} else {
sess->paging.ue_requested_pdu_session_establishment_done = true;
2021-06-06 13:35:46 +00:00
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
2021-01-03 05:50:59 +00:00
}
2020-06-17 05:22:28 +00:00
2020-08-13 00:31:22 +00:00
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
2021-01-18 16:48:35 +00:00
if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) {
smf_n1_n2_message_transfer_param_t param;
memset(&param, 0, sizeof(param));
param.state = SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN;
param.n2smbuf =
ngap_build_pdu_session_resource_release_command_transfer(
sess, SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN,
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
ogs_assert(param.n2smbuf);
param.skip_ind = true;
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
} else {
smf_sbi_send_sm_context_updated_data_up_cnx_state(
sess, stream, OpenAPI_up_cnx_state_DEACTIVATED);
}
/*
* You should not change the following order to support
* OGS_PFCP_MODIFY_REMOVE|OGS_PFCP_MODIFY_CREATE.
*
* 1. if (flags & OGS_PFCP_MODIFY_REMOVE) {
* 2. } else if (flags & OGS_PFCP_MODIFY_CREATE) {
* }
*/
} else if (flags & OGS_PFCP_MODIFY_REMOVE) {
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
smf_sess_delete_indirect_data_forwarding(sess);
/*
* OGS_PFCP_MODIFY_CREATE remains.
* So now we do some extra work to create an indirect tunnel.
*/
if (flags & OGS_PFCP_MODIFY_CREATE) {
smf_sess_create_indirect_data_forwarding(sess);
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_pdr_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_CREATE,
0));
} else if (flags & OGS_PFCP_MODIFY_HANDOVER_CANCEL) {
smf_sbi_send_sm_context_updated_data_ho_state(
sess, stream, OpenAPI_ho_state_CANCELLED);
}
2021-11-14 12:07:56 +00:00
} else if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
smf_n1_n2_message_transfer_param_t param;
smf_bearer_t *next = NULL;
2021-11-14 12:07:56 +00:00
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
2021-11-14 12:07:56 +00:00
memset(&param, 0, sizeof(param));
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
param.n1smbuf = gsm_build_pdu_session_modification_command(
sess,
2021-11-14 12:07:56 +00:00
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE,
OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION);
ogs_assert(param.n1smbuf);
param.n2smbuf =
ngap_build_pdu_session_resource_release_request_transfer(
sess,
2021-11-14 12:07:56 +00:00
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
ogs_assert(param.n2smbuf);
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
ogs_list_for_each_entry_safe(&sess->qos_flow_to_modify_list,
next, qos_flow, to_modify_node)
smf_bearer_remove(qos_flow);
2021-11-14 12:07:56 +00:00
} else if (flags & OGS_PFCP_MODIFY_UE_REQUESTED) {
ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL;
smf_bearer_t *next = NULL;
2021-11-14 12:07:56 +00:00
ogs_assert(stream);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
n1smbuf = gsm_build_pdu_session_modification_command(
sess, sess->pti,
2021-11-14 12:07:56 +00:00
OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE,
OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION);
ogs_assert(n1smbuf);
n2smbuf = ngap_build_pdu_session_resource_release_request_transfer(
sess,
2021-11-14 12:07:56 +00:00
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
ogs_assert(n2smbuf);
smf_sbi_send_sm_context_updated_data_n1_n2_message(
sess, stream, n1smbuf,
OpenAPI_n2_sm_info_type_PDU_RES_MOD_REQ, n2smbuf);
ogs_list_for_each_entry_safe(&sess->qos_flow_to_modify_list,
next, qos_flow, to_modify_node)
smf_bearer_remove(qos_flow);
2021-11-14 12:07:56 +00:00
} else {
ogs_fatal("Unknown flags [0x%llx]", (long long)flags);
ogs_assert_if_reached();
}
2021-01-01 02:07:08 +00:00
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
ogs_pkbuf_t *n2smbuf = ngap_build_handover_command_transfer(sess);
ogs_assert(n2smbuf);
smf_sbi_send_sm_context_updated_data(
sess, stream, 0, OpenAPI_ho_state_PREPARED,
NULL, OpenAPI_n2_sm_info_type_HANDOVER_CMD, n2smbuf);
2021-11-14 12:07:56 +00:00
} else if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
smf_n1_n2_message_transfer_param_t param;
2021-01-01 02:07:08 +00:00
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
memset(&param, 0, sizeof(param));
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
param.n1smbuf = gsm_build_pdu_session_modification_command(
sess,
2021-11-14 12:07:56 +00:00
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE,
OGS_NAS_CREATE_NEW_QOS_FLOW_DESCRIPTION);
ogs_assert(param.n1smbuf);
param.n2smbuf =
ngap_build_pdu_session_resource_modify_request_transfer(
sess, true);
2021-11-14 12:07:56 +00:00
ogs_assert(param.n2smbuf);
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
2021-11-14 12:07:56 +00:00
} else {
ogs_fatal("Unknown flags [0x%llx]", (long long)flags);
ogs_assert_if_reached();
}
} else if (flags &
(OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE|
OGS_PFCP_MODIFY_QOS_MODIFY)) {
smf_n1_n2_message_transfer_param_t param;
uint8_t qos_rule_code = 0;
uint8_t qos_flow_description_code = 0;
if (flags & OGS_PFCP_MODIFY_TFT_NEW) {
qos_rule_code = OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE;
} else if (flags & OGS_PFCP_MODIFY_TFT_ADD) {
qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS;
} else if (flags & OGS_PFCP_MODIFY_TFT_REPLACE) {
qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_PACKET_FILTERS;
} else if (flags & OGS_PFCP_MODIFY_TFT_DELETE) {
qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS;
}
if (flags & OGS_PFCP_MODIFY_QOS_CREATE) {
ogs_assert_if_reached();
} else if (flags & OGS_PFCP_MODIFY_QOS_MODIFY) {
qos_flow_description_code = OGS_NAS_MODIFY_NEW_QOS_FLOW_DESCRIPTION;
} else if (flags & OGS_PFCP_MODIFY_QOS_DELETE) {
ogs_assert_if_reached();
}
if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
2021-11-14 12:07:56 +00:00
memset(&param, 0, sizeof(param));
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
param.n1smbuf = gsm_build_pdu_session_modification_command(
sess,
2021-11-14 12:07:56 +00:00
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
qos_rule_code, qos_flow_description_code);
ogs_assert(param.n1smbuf);
param.n2smbuf =
ngap_build_pdu_session_resource_modify_request_transfer(
sess,
(flags & OGS_PFCP_MODIFY_QOS_MODIFY) ? true : false);
ogs_assert(param.n2smbuf);
2021-01-01 02:07:08 +00:00
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
2021-11-14 12:07:56 +00:00
} else if (flags & OGS_PFCP_MODIFY_UE_REQUESTED) {
ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL;
ogs_assert(stream);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
n1smbuf = gsm_build_pdu_session_modification_command(
sess, sess->pti,
2021-11-14 12:07:56 +00:00
qos_rule_code, qos_flow_description_code);
ogs_assert(n1smbuf);
n2smbuf = ngap_build_pdu_session_resource_modify_request_transfer(
sess,
2021-11-14 12:07:56 +00:00
(flags & OGS_PFCP_MODIFY_QOS_MODIFY) ? true : false);
ogs_assert(n2smbuf);
smf_sbi_send_sm_context_updated_data_n1_n2_message(sess, stream,
n1smbuf, OpenAPI_n2_sm_info_type_PDU_RES_MOD_REQ, n2smbuf);
} else {
ogs_fatal("Unknown flags [0x%llx]", (long long)flags);
ogs_assert_if_reached();
}
}
2020-06-17 05:22:28 +00:00
}
2022-05-14 21:27:54 +00:00
int smf_5gc_n4_handle_session_deletion_response(
smf_sess_t *sess, ogs_sbi_stream_t *stream, int trigger,
2020-06-17 05:22:28 +00:00
ogs_pfcp_session_deletion_response_t *rsp)
{
2020-07-04 03:14:48 +00:00
int status = 0;
2020-06-22 03:07:14 +00:00
ogs_debug("Session Deletion Response [5gc]");
2022-05-14 21:27:54 +00:00
ogs_assert(rsp);
2020-07-02 05:50:23 +00:00
ogs_assert(trigger);
2020-07-04 03:14:48 +00:00
status = OGS_SBI_HTTP_STATUS_OK;
if (!sess) {
ogs_warn("No Context");
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
}
2020-06-22 03:07:14 +00:00
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
2020-07-04 03:14:48 +00:00
ogs_warn("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
status = sbi_status_from_pfcp(rsp->cause.u8);
2020-06-22 03:07:14 +00:00
}
} else {
ogs_error("No Cause");
2020-07-04 03:14:48 +00:00
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
}
if (status != OGS_SBI_HTTP_STATUS_OK) {
char *strerror = ogs_msprintf(
"PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
2021-11-14 12:07:56 +00:00
if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED ||
trigger == OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT) {
ogs_assert(stream);
smf_sbi_send_sm_context_update_error(
stream, status, strerror, NULL, NULL, NULL);
2021-11-14 12:07:56 +00:00
} else if (trigger == OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) {
ogs_assert(stream);
ogs_assert(true ==
ogs_sbi_server_send_error(
stream, status, NULL, strerror, NULL));
} else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) {
/* No stream - Nothing */
} else {
ogs_fatal("Unknown trigger [%d]", trigger);
ogs_assert_if_reached();
}
ogs_error("%s", strerror);
2020-07-04 03:14:48 +00:00
ogs_free(strerror);
2022-05-14 21:27:54 +00:00
return status;
2020-06-22 03:07:14 +00:00
}
2020-07-04 03:14:48 +00:00
ogs_assert(sess);
2022-05-14 21:27:54 +00:00
return status;
2020-06-17 05:22:28 +00:00
}
2022-05-14 21:27:54 +00:00
/* Returns OGS_PFCP_CAUSE_REQUEST_ACCEPTED on success,
* other cause value on failure */
uint8_t smf_epc_n4_handle_session_establishment_response(
2020-04-26 19:36:05 +00:00
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_establishment_response_t *rsp)
{
uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
smf_bearer_t *bearer = NULL;
2020-04-26 19:36:05 +00:00
ogs_gtp_xact_t *gtp_xact = NULL;
2020-04-26 19:36:05 +00:00
ogs_pfcp_f_seid_t *up_f_seid = NULL;
ogs_assert(sess);
2020-04-26 19:36:05 +00:00
ogs_assert(xact);
ogs_assert(rsp);
ogs_debug("Session Establishment Response [epc]");
2020-04-26 19:36:05 +00:00
gtp_xact = xact->assoc_xact;
ogs_assert(gtp_xact);
ogs_pfcp_xact_commit(xact);
if (rsp->up_f_seid.presence == 0) {
ogs_error("No UP F-SEID");
cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
2020-04-26 19:36:05 +00:00
}
if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
2020-07-04 03:14:48 +00:00
ogs_warn("PFCP Cause [%d] : Not Accepted", rsp->cause.u8);
cause_value = rsp->cause.u8;
2020-04-26 19:36:05 +00:00
}
} else {
ogs_error("No Cause");
cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
2020-04-26 19:36:05 +00:00
}
if (cause_value == OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
int i;
uint8_t offending_ie_value = 0;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&cause_value, &offending_ie_value);
if (!pdr)
break;
}
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
2021-03-15 01:01:55 +00:00
far = pdr->far;
ogs_assert(far);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) {
smf_bearer_t *pdr_bearer = NULL;
2021-03-15 01:01:55 +00:00
if (far->dst_if == OGS_PFCP_INTERFACE_CP_FUNCTION)
ogs_pfcp_far_teid_hash_set(far);
pdr_bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
if (pdr_bearer) {
2021-03-15 01:01:55 +00:00
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (pdr_bearer->pgw_s5u_addr)
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr);
if (pdr_bearer->pgw_s5u_addr)
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr6);
2021-03-15 01:01:55 +00:00
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_OK ==
ogs_pfcp_f_teid_to_sockaddr(
2021-03-15 01:01:55 +00:00
&pdr->f_teid, pdr->f_teid_len,
&pdr_bearer->pgw_s5u_addr,
&pdr_bearer->pgw_s5u_addr6));
pdr_bearer->pgw_s5u_teid = pdr->f_teid.teid;
2021-03-15 01:01:55 +00:00
}
}
} else if (pdr->src_if == OGS_PFCP_INTERFACE_CP_FUNCTION) {
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_ERROR != ogs_pfcp_setup_pdr_gtpu_node(pdr));
}
}
}
Introduce Gn interface (GTPv1C) Support to PGW (#1351) * [CORE] tlv: Store mode in ogs_tlv_t This allows specifying the format of the IE for each individual IE, hence allowing messages containing IEs formatted in different ways. This is needed in order to support parsing GTPv1-C, since messages contain IEs with different structure (TLV vs TV). Hence, this is a preparation patch to add support for parsing TVs in ogs-tlv.c/.h. * [CORE] tlv: Support parsing msg with both TLV and TV in it IEs of type TV are sometimes used in GTPv1-C. Current tlv parser/builder doesn't provide with ways to parse messages which contain TV formatted IEs. This patch adds the relevant types and ways to encode/decode them. Furthermore, the current parser/builder allows parsing/building messages containing the exact same format in all its IEs. A new parser function is added which allows parsing messages of different types (TV, TLV) mixed in the same message. In order to be able to do so, it uses the general msg_mode passed to it in order to know the general TLV format (in essence, the length of the Tag field, and also the length of the Length field if applicable each IE). Looking up the instance in the TLV description is left undone and hadcoded to 0, since the only user so far requiring this API is GTPv1-C, which has no instances. * [CORE] tlv: Support repeated tag+instance parsing TLV message In GTPv2C, repeated IEs (same tag) are easily differentiated by the Instance byte, which provides info to match different decoded structures. In GTPv1C though, there's no Instance byte, and we still encounter repeated IEs (like GSN Address in Create PDP Context Request). Hence, the TLV decoder needs to be updated to track count of IEs found (identified by tag+instance, where instance is always 0 in GTPv1C) and get the proper description index + offset into the decoded structure. * [GTP]: Move GTPv2-C specifics to its own libgtp subdir This will allow adding GTPv1-C code by the side. Most GTPv2 code is left in this patch as "gtp" instead of renaming it to "gtp2" in order to avoid massive changes. It can be done at a later stage if wanted. * [GTP] Support generating GTPv1-C messages * [SMF] Add Gn interface support This patch introduces GTPv1C support to open5gs-smfd. With it, open5gs-becomes a GGSN too, where SGSN can connect to, hence supporting GERAN and UTRAN networks.
2022-02-18 13:23:45 +00:00
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
return cause_value;
2020-04-26 19:36:05 +00:00
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");
return OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
}
2020-04-26 19:36:05 +00:00
/* UP F-SEID */
up_f_seid = rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->upf_n4_seid = be64toh(up_f_seid->seid);
return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
2020-04-26 19:36:05 +00:00
}
2020-06-17 05:22:28 +00:00
void smf_epc_n4_handle_session_modification_response(
2020-04-26 19:36:05 +00:00
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_gtp2_message_t *recv_message,
2020-04-26 19:36:05 +00:00
ogs_pfcp_session_modification_response_t *rsp)
{
int i;
2020-04-26 19:36:05 +00:00
smf_bearer_t *bearer = NULL;
ogs_gtp_xact_t *gtp_xact = NULL;
uint8_t gtp_pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
uint8_t gtp_cause = OGS_GTP2_CAUSE_UNDEFINED_VALUE;
2020-08-13 00:31:22 +00:00
uint64_t flags = 0;
2020-04-26 19:36:05 +00:00
uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
OGS_LIST(pdr_to_create_list);
2020-04-26 19:36:05 +00:00
ogs_assert(xact);
ogs_assert(rsp);
ogs_debug("Session Modification Response [epc]");
if (flags & OGS_PFCP_MODIFY_SESSION) {
/* If smf_epc_pfcp_send_pdr_modification_request() is called */
} else {
/* If smf_epc_pfcp_send_bearer_modification_request() is called */
bearer = xact->data;
ogs_assert(bearer);
}
2020-08-13 00:31:22 +00:00
flags = xact->modify_flags;
ogs_assert(flags);
2020-04-26 19:36:05 +00:00
/* OGS_PFCP_MODIFY_URR: Modification Response was originally triggered by
PFCP Session Report Request, xact->assoc_xact is not a gtp_xact. No
need to do anything. */
if (!(flags & OGS_PFCP_MODIFY_URR)) {
gtp_xact = xact->assoc_xact;
gtp_pti = xact->gtp_pti;
gtp_cause = xact->gtp_cause;
}
ogs_list_copy(&pdr_to_create_list, &xact->pdr_to_create_list);
2020-04-26 19:36:05 +00:00
ogs_pfcp_xact_commit(xact);
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++) {
pdr = ogs_pfcp_handle_created_pdr(
&sess->pfcp, &rsp->created_pdr[i],
&pfcp_cause_value, &offending_ie_value);
if (!pdr)
break;
}
ogs_list_for_each_entry(&pdr_to_create_list, pdr, to_create_node) {
2021-03-15 01:01:55 +00:00
far = pdr->far;
ogs_assert(far);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) {
smf_bearer_t *pdr_bearer = NULL;
2021-03-15 01:01:55 +00:00
if (far->dst_if == OGS_PFCP_INTERFACE_CP_FUNCTION)
ogs_pfcp_far_teid_hash_set(far);
pdr_bearer = smf_bearer_find_by_pdr_id(sess, pdr->id);
if (pdr_bearer) {
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (pdr_bearer->pgw_s5u_addr)
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr);
if (pdr_bearer->pgw_s5u_addr)
ogs_freeaddrinfo(pdr_bearer->pgw_s5u_addr6);
ogs_assert(OGS_OK ==
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&pdr_bearer->pgw_s5u_addr,
&pdr_bearer->pgw_s5u_addr6));
pdr_bearer->pgw_s5u_teid = pdr->f_teid.teid;
}
2021-03-15 01:01:55 +00:00
}
} else if (pdr->src_if == OGS_PFCP_INTERFACE_CP_FUNCTION) {
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_ERROR != ogs_pfcp_setup_pdr_gtpu_node(pdr));
}
}
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_REMOVE) {
ogs_assert(bearer);
2020-04-26 19:36:05 +00:00
smf_bearer_remove(bearer);
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
ogs_assert(bearer);
ogs_assert(OGS_OK == smf_gtp2_send_create_bearer_request(bearer));
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
/*
* TS23.214
* 6.3.1.7 Procedures with modification of bearer
* p50
* 2. ...
* For "PGW/MME initiated bearer deactivation procedure",
* PGW-C shall indicate PGW-U to stop counting and stop
* forwarding downlink packets for the affected bearer(s).
*/
if (gtp_xact) {
/*
* 1. MME sends Bearer Resource Command to SGW/SMF.
* 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME
* 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF
*/
ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
int rv;
ogs_assert(bearer);
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.teid = sess->sgw_s5c_teid;
h.type = OGS_GTP2_DELETE_BEARER_REQUEST_TYPE;
pkbuf = smf_s5c_build_delete_bearer_request(
h.type, bearer, gtp_pti, gtp_cause);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(gtp_xact, &h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
/* IMPORTANT:
*
* When initiaited by Bearer Resource Command,
* there must be bearer context in the Transaction.
* Otherwise, the bearer context cannot be found
* in GTP response message.
*
* For example,
* 1. MME sends Bearer Resource Command to SGW-C, SMF.
* 2. SMF sends Update/Delete Bearer Request to the SGW-C, MME.
* 3. MME sends Update/Delete Bearer Response to thw SGW-C, SMF.
*
* On number 3 step, if MME sends Response without Bearer Context,
* we need a way to find Bearer context.
*
* To do this, I saved Bearer Context in Transaction Context.
*/
gtp_xact->data = bearer;
rv = ogs_gtp_xact_commit(gtp_xact);
ogs_expect(rv == OGS_OK);
} else {
if (flags & OGS_PFCP_MODIFY_SESSION) {
/*
* 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME.
* 2. MME sends Delete Bearer Response to SGW/SMF.
*
* OR
*
* 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG.
* 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF.
*/
smf_bearer_t *linked_bearer =
ogs_list_first(&sess->bearer_list);
ogs_assert(linked_bearer);
ogs_assert(OGS_OK ==
smf_gtp2_send_delete_bearer_request(
linked_bearer, gtp_pti, gtp_cause));
} else {
/*
* 1. RX : Session-Termination Request
* 2. GX : Re-Auth-Request(Charging-Rule-Remove)
* 3. RX : Session-Termination Answer
* 4. PFCP Session Modification Request(Buffering)
* 5. PFCP Session Modification Answer(Buffering)
* 6. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME.
* 7. E-RABReleaseCommand + Deactivate EPS bearer context request
* 8. E-RABReleaseResponse
* 9. UplinkNASTransport + Deactivate EPS bearer context accept
* 10. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW-C
* 11. PFCP Session Modification Request/Response(Remove PDR/FAR)
* 12. SGW-C sends Delete Bearer Response(DECIATED BEARER) to SMF
* 13. PFCP Session Modification Request/Response(Remove PDR/FAR)
*/
ogs_assert(bearer);
ogs_assert(OGS_OK ==
smf_gtp2_send_delete_bearer_request(
bearer,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
gtp_cause));
}
}
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
if (gtp_xact) {
/* SMF send Update PDP Context Response (GTPv1C) to SGSN */
if (gtp_xact->gtp_version == 1) {
bearer = gtp_xact->data;
smf_gtp1_send_update_pdp_context_response(bearer, gtp_xact);
} else {
/* SMF send Modify Bearer Response (GTPv2C) to SGW-C */
ogs_gtp2_indication_t *indication = NULL;
ogs_assert(recv_message);
ogs_gtp2_modify_bearer_request_t *gtp_req =
&recv_message->modify_bearer_request;
ogs_assert(OGS_OK == smf_gtp2_send_modify_bearer_response(
sess, gtp_xact, gtp_req, true));
/* Check if Handover from Non-3GPP to 3GPP */
if (gtp_req->indication_flags.presence &&
gtp_req->indication_flags.data &&
gtp_req->indication_flags.len) {
indication = gtp_req->indication_flags.data;
}
if (indication && indication->handover_indication) {
ogs_assert(OGS_OK == smf_epc_pfcp_send_deactivation(sess,
OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP));
}
}
} else {
/* Nothing */
}
}
2020-04-26 19:36:05 +00:00
}
uint8_t smf_epc_n4_handle_session_deletion_response(
2020-04-26 19:36:05 +00:00
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_pfcp_session_deletion_response_t *rsp)
{
smf_bearer_t *bearer = NULL;
unsigned int i;
2020-04-26 19:36:05 +00:00
ogs_assert(sess);
2020-04-26 19:36:05 +00:00
ogs_assert(xact);
ogs_assert(rsp);
ogs_debug("Session Deletion Response [epc]");
2020-04-26 19:36:05 +00:00
ogs_pfcp_xact_commit(xact);
if (!rsp->cause.presence) {
2020-04-26 19:36:05 +00:00
ogs_error("No Cause");
return OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
2020-04-26 19:36:05 +00:00
}
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("PFCP Cause[%d] : Not Accepted", rsp->cause.u8);
return rsp->cause.u8;
2020-04-26 19:36:05 +00:00
}
ogs_assert(sess);
bearer = smf_default_bearer_in_sess(sess);
for (i = 0; i < OGS_ARRAY_SIZE(rsp->usage_report); i++) {
2022-05-14 21:27:54 +00:00
ogs_pfcp_tlv_usage_report_session_deletion_response_t *use_rep =
&rsp->usage_report[i];
uint32_t urr_id;
ogs_pfcp_volume_measurement_t volume;
if (use_rep->presence == 0)
break;
if (use_rep->urr_id.presence == 0)
continue;
urr_id = use_rep->urr_id.u32;
if (!bearer || !bearer->urr || bearer->urr->id != urr_id)
continue;
2022-05-14 21:27:54 +00:00
ogs_pfcp_parse_volume_measurement(
&volume, &use_rep->volume_measurement);
if (volume.ulvol)
sess->gy.ul_octets += volume.uplink_volume;
if (volume.dlvol)
sess->gy.dl_octets += volume.downlink_volume;
sess->gy.duration += use_rep->duration_measurement.u32;
}
return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
2020-04-26 19:36:05 +00:00
}
2021-01-18 16:48:35 +00:00
void smf_n4_handle_session_report_request(
smf_sess_t *sess, ogs_pfcp_xact_t *pfcp_xact,
ogs_pfcp_session_report_request_t *pfcp_req)
{
smf_bearer_t *qos_flow = NULL;
smf_bearer_t *bearer = NULL;
2021-01-18 16:48:35 +00:00
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_report_type_t report_type;
uint8_t cause_value = 0;
uint16_t pdr_id = 0;
unsigned int i;
2021-01-18 16:48:35 +00:00
ogs_assert(pfcp_xact);
ogs_assert(pfcp_req);
ogs_debug("Session Report Request");
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
2021-01-18 16:48:35 +00:00
if (!sess) {
ogs_warn("No Context");
cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
}
if (pfcp_req->report_type.presence == 0) {
ogs_error("No Report Type");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
2021-01-18 16:48:35 +00:00
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
2021-01-18 16:48:35 +00:00
ogs_pfcp_send_error_message(pfcp_xact, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
cause_value, 0);
return;
}
ogs_assert(sess);
report_type.value = pfcp_req->report_type.u8;
if (report_type.downlink_data_report) {
ogs_pfcp_downlink_data_service_information_t *info = NULL;
uint8_t paging_policy_indication_value = 0;
uint8_t qfi = 0;
if (pfcp_req->downlink_data_report.presence) {
if (pfcp_req->downlink_data_report.
downlink_data_service_information.presence) {
info = pfcp_req->downlink_data_report.
downlink_data_service_information.data;
if (info) {
if (info->qfii && info->ppi) {
paging_policy_indication_value =
info->paging_policy_indication_value;
qfi = info->qfi;
} else if (info->qfii) {
qfi = info->qfi;
} else if (info->ppi) {
paging_policy_indication_value =
info->paging_policy_indication_value;
} else {
ogs_error("Invalid Downlink Data Service Information");
}
if (paging_policy_indication_value) {
ogs_warn("Not implement - "
"Paging Policy Indication Value");
ogs_pfcp_send_error_message(pfcp_xact, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
OGS_GTP2_CAUSE_SERVICE_NOT_SUPPORTED, 0);
2021-01-18 16:48:35 +00:00
return;
}
if (qfi) {
qos_flow = smf_qos_flow_find_by_qfi(sess, qfi);
if (!qos_flow)
ogs_error("Cannot find the QoS Flow[%d]", qfi);
}
} else {
ogs_error("No Info");
}
}
if (pfcp_req->downlink_data_report.pdr_id.presence) {
pdr = ogs_pfcp_pdr_find(&sess->pfcp,
pfcp_req->downlink_data_report.pdr_id.u16);
if (!pdr)
ogs_error("Cannot find the PDR-ID[%d]", pdr_id);
} else {
ogs_error("No PDR-ID");
}
} else {
ogs_error("No Downlink Data Report");
}
if (!pdr || !qos_flow) {
ogs_error("No Context [%p:%p]", pdr, qos_flow);
ogs_pfcp_send_error_message(pfcp_xact, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
cause_value, 0);
return;
2021-01-18 16:48:35 +00:00
}
if (sess->paging.ue_requested_pdu_session_establishment_done == true) {
smf_n1_n2_message_transfer_param_t param;
memset(&param, 0, sizeof(param));
param.state = SMF_NETWORK_TRIGGERED_SERVICE_REQUEST;
param.n2smbuf =
ngap_build_pdu_session_resource_setup_request_transfer(sess);
2021-01-18 16:48:35 +00:00
ogs_assert(param.n2smbuf);
param.n1n2_failure_txf_notif_uri = true;
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
}
}
2021-01-18 16:48:35 +00:00
if (report_type.error_indication_report) {
2021-01-18 16:48:35 +00:00
smf_ue_t *smf_ue = sess->smf_ue;
smf_sess_t *error_indication_session = NULL;
ogs_assert(smf_ue);
error_indication_session = smf_sess_find_by_error_indication_report(
smf_ue, &pfcp_req->error_indication_report);
if (error_indication_session) {
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_pdr_modification_request(
error_indication_session, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
OGS_PFCP_MODIFY_ERROR_INDICATION,
0));
}
}
2021-01-18 16:48:35 +00:00
if (report_type.usage_report) {
bearer = smf_default_bearer_in_sess(sess);
for (i = 0; i < OGS_ARRAY_SIZE(pfcp_req->usage_report); i++) {
2022-05-14 21:27:54 +00:00
ogs_pfcp_tlv_usage_report_session_report_request_t *use_rep =
&pfcp_req->usage_report[i];
uint32_t urr_id;
ogs_pfcp_volume_measurement_t volume;
if (use_rep->presence == 0)
break;
if (use_rep->urr_id.presence == 0)
continue;
urr_id = use_rep->urr_id.u32;
if (!bearer || !bearer->urr || bearer->urr->id != urr_id)
continue;
2022-05-14 21:27:54 +00:00
ogs_pfcp_parse_volume_measurement(
&volume, &use_rep->volume_measurement);
if (volume.ulvol)
sess->gy.ul_octets += volume.uplink_volume;
if (volume.dlvol)
sess->gy.dl_octets += volume.downlink_volume;
sess->gy.duration += use_rep->duration_measurement.u32;
}
switch(smf_use_gy_iface()) {
case 1:
2022-05-14 21:27:54 +00:00
smf_gy_send_ccr(sess, pfcp_xact,
OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST);
break;
case -1:
ogs_error("No Gy Diameter Peer");
/* TODO: terminate connection */
break;
/* default: continue below */
}
}
/* TS 29.244 sec 8.2.21: At least one bit shall be set to "1". Several bits may be set to "1". */
if (report_type.downlink_data_report ||
report_type.error_indication_report ||
report_type.usage_report) {
ogs_assert(OGS_OK ==
smf_pfcp_send_session_report_response(
pfcp_xact, sess, OGS_PFCP_CAUSE_REQUEST_ACCEPTED));
2021-01-18 16:48:35 +00:00
} else {
ogs_error("Not supported Report Type[%d]", report_type.value);
ogs_assert(OGS_OK ==
smf_pfcp_send_session_report_response(
pfcp_xact, sess, OGS_PFCP_CAUSE_SYSTEM_FAILURE));
2021-01-18 16:48:35 +00:00
}
}