diff options
Diffstat (limited to 'tests/libosmo-pfcp/pfcp_test.c')
-rw-r--r-- | tests/libosmo-pfcp/pfcp_test.c | 512 |
1 files changed, 512 insertions, 0 deletions
diff --git a/tests/libosmo-pfcp/pfcp_test.c b/tests/libosmo-pfcp/pfcp_test.c new file mode 100644 index 0000000..189622e --- /dev/null +++ b/tests/libosmo-pfcp/pfcp_test.c @@ -0,0 +1,512 @@ +/* + * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <stdio.h> +#include <errno.h> + +#include <osmocom/core/application.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/msgb.h> + +#include <osmocom/pfcp/pfcp_msg.h> + +void *ctx; + +/* struct osmo_sockaddr */ +#define v4_ue { \ + .u.sin = { \ + .sin_family = AF_INET, \ + .sin_addr = { 0x1700a8c0 }, \ + } \ +} + +/* struct osmo_sockaddr */ +#define v4_gtp { \ + .u.sin = { \ + .sin_family = AF_INET, \ + .sin_addr = { 0x0708090a }, \ + } \ +} + +/* struct osmo_pfcp_ie_f_teid */ +#define f_teid_access_local { \ + .choose_flag = true, \ + .choose = { \ + .ipv4_addr = true, \ + }, \ +} + +/* struct osmo_pfcp_ie_f_teid */ +#define f_teid_created { \ + .fixed = { \ + .teid = 1234, \ + .ip_addr = { \ + .v4_present = true, \ + .v4 = v4_gtp, \ + }, \ + }, \ +} + +/* struct osmo_pfcp_ie_outer_header_creation */ +#define ohc_access { \ + .desc_bits = { 0x01 }, \ + .teid_present = true, \ + .teid = 0xabcdef, \ + .ip_addr = { \ + .v4_present = true, \ + .v4 = v4_gtp, \ + }, \ +} + +/* struct osmo_pfcp_ie_apply_action */ +#define aa_forw { \ + .bits = { 0x02 }, \ +} + +/* struct osmo_pfcp_ie_f_seid */ +#define f_seid { \ + .seid = 0x1234567890abcdef, \ + .ip_addr = { \ + .v4_present = true, \ + .v4 = v4_gtp, \ + }, \ +} + +struct osmo_pfcp_msg tests[] = { + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_HEARTBEAT_REQ, + .sequence_nr = 1, + }, + .ies.heartbeat_req = { + .recovery_time_stamp = 1234, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_HEARTBEAT_RESP, + .sequence_nr = 2, + }, + .ies.heartbeat_resp = { + .recovery_time_stamp = 5678, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_ASSOC_SETUP_REQ, + .sequence_nr = 3, + }, + .ies.assoc_setup_req = { + .node_id = { + .type = OSMO_PFCP_NODE_ID_T_IPV4, + .ip.u.sin = { + .sin_family = AF_INET, + .sin_addr = { 0x01020304 }, + }, + }, + .recovery_time_stamp = 0x2b2b2b2b, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_ASSOC_SETUP_RESP, + .sequence_nr = 4, + }, + .ies.assoc_setup_resp = { + .node_id = { + .type = OSMO_PFCP_NODE_ID_T_FQDN, + .fqdn = "example.com", + }, + .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, + .recovery_time_stamp = 0x2b2b2b2b, + .up_function_features_present = true, + .up_function_features.bits = { 1, 2 }, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_ASSOC_RELEASE_REQ, + .sequence_nr = 5, + }, + .ies.assoc_release_req = { + .node_id = { + .type = OSMO_PFCP_NODE_ID_T_IPV6, + .ip.u.sin6 = { + .sin6_family = AF_INET6, + .sin6_addr = {{{ 1, 2, 3, 4 }}}, + }, + }, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP, + .sequence_nr = 6, + }, + .ies.assoc_release_resp = { + .node_id = { + .type = OSMO_PFCP_NODE_ID_T_IPV4, + .ip.u.sin = { + .sin_family = AF_INET, + .sin_addr = { 0x01020304 }, + }, + }, + .cause = OSMO_PFCP_CAUSE_REQUEST_REJECTED, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_EST_REQ, + .sequence_nr = 7, + .seid_present = true, + .seid = 0, + }, + .ies.session_est_req = { + .node_id = { + .type = OSMO_PFCP_NODE_ID_T_IPV4, + .ip.u.sin = { + .sin_family = AF_INET, + .sin_addr = { 0x0100007f }, + }, + }, + .cp_f_seid_present = true, + .cp_f_seid = f_seid, + .create_pdr_count = 2, + .create_pdr = { + { + .pdr_id = 1, + .precedence = 255, + .pdi = { + .source_iface = OSMO_PFCP_SOURCE_IFACE_CORE, + .ue_ip_address_present = true, + .ue_ip_address = { + .ip_is_destination = true, + .ip_addr = { + .v4_present = true, + .v4 = v4_ue, + }, + }, + }, + .far_id_present = true, + .far_id = 1, + }, + { + .pdr_id = 2, + .precedence = 255, + .pdi = { + .source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS, + .local_f_teid_present = true, + .local_f_teid = f_teid_access_local, + }, + .outer_header_removal_present = true, + .outer_header_removal = { + .desc = OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, + }, + .far_id_present = true, + .far_id = 2, + }, + }, + .create_far_count = 2, + .create_far = { + { + .far_id = 1, + .forw_params_present = true, + .forw_params = { + .destination_iface = OSMO_PFCP_DEST_IFACE_ACCESS, + .outer_header_creation_present = true, + .outer_header_creation = ohc_access, + }, + .apply_action = aa_forw, + }, + { + .far_id = 2, + .forw_params_present = true, + .forw_params = { + .destination_iface = OSMO_PFCP_DEST_IFACE_CORE, + }, + .apply_action = aa_forw, + }, + }, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_EST_RESP, + .sequence_nr = 8, + .seid_present = true, + .seid = 0x0123456789abcdef, + }, + .ies.session_est_resp = { + .node_id = { + .type = OSMO_PFCP_NODE_ID_T_IPV4, + .ip.u.sin = { + .sin_family = AF_INET, + .sin_addr = { 0x0200007f }, + }, + }, + .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, + .up_f_seid_present = true, + .up_f_seid = f_seid, + .created_pdr_count = 2, + .created_pdr = { + { + .pdr_id = 1, + }, + { + .pdr_id = 2, + .local_f_teid_present = true, + .local_f_teid = f_teid_created, + }, + }, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_MOD_REQ, + .sequence_nr = 9, + .seid_present = true, + .seid = 0, + }, + .ies.session_mod_req = { + .remove_pdr_count = 1, + .remove_pdr = { + { + .pdr_id = 1, + }, + }, + .remove_far_count = 1, + .remove_far = { + { + .far_id = 1, + }, + }, + .create_pdr_count = 1, + .create_pdr = { + { + .pdr_id = 3, + .precedence = 255, + .pdi = { + .source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS, + .local_f_teid_present = true, + .local_f_teid = f_teid_access_local, + }, + .outer_header_removal_present = true, + .outer_header_removal = { + .desc = OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, + }, + .far_id_present = true, + .far_id = 3, + }, + }, + .create_far_count = 1, + .create_far = { + { + .far_id = 3, + .forw_params_present = true, + .forw_params = { + .destination_iface = OSMO_PFCP_DEST_IFACE_ACCESS, + .outer_header_creation_present = true, + .outer_header_creation = ohc_access, + }, + .apply_action = aa_forw, + }, + }, + .upd_pdr_count = 1, + .upd_pdr = { + { + .pdr_id = 1, + .pdi = { + .source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS, + .local_f_teid_present = true, + .local_f_teid = f_teid_access_local, + }, + .outer_header_removal_present = true, + .outer_header_removal = { + .desc = OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, + }, + .far_id_present = true, + .far_id = 1, + }, + }, + .upd_far_count = 1, + .upd_far = { + { + .far_id = 1, + .upd_forw_params_present = true, + .upd_forw_params = { + .destination_iface = OSMO_PFCP_DEST_IFACE_CORE, + .network_inst_present = true, + .network_inst = { + .str = "internet", + }, + }, + .apply_action = aa_forw, + }, + }, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_MOD_RESP, + .sequence_nr = 10, + .seid_present = true, + .seid = 0x0123456789abcdef, + }, + .ies.session_mod_resp = { + .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, + .created_pdr_count = 1, + .created_pdr = { + { + .pdr_id = 3, + .local_f_teid_present = true, + .local_f_teid = f_teid_created, + }, + }, + .updated_pdr_count = 1, + .updated_pdr = { + { + .pdr_id = 1, + .local_f_teid_present = true, + .local_f_teid = f_teid_created, + }, + }, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_MOD_RESP, + .sequence_nr = 11, + .seid_present = true, + .seid = 0x0123456789abcdef, + }, + .ies.session_mod_resp = { + .cause = OSMO_PFCP_CAUSE_MANDATORY_IE_MISSING, + .offending_ie_present = true, + .offending_ie = OSMO_PFCP_IEI_APPLY_ACTION, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_DEL_REQ, + .sequence_nr = 12, + .seid_present = true, + .seid = 0x0123456789abcdef, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_DEL_RESP, + .sequence_nr = 13, + .seid_present = true, + .seid = 0x0123456789abcdef, + }, + .ies.session_del_resp = { + .cause = OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC, + }, + }, + { + .h = { + .version = 1, + .message_type = OSMO_PFCP_MSGT_SESSION_DEL_RESP, + .sequence_nr = 13, + .seid_present = true, + .seid = 0x0123456789abcdef, + }, + .ies.session_del_resp = { + .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, + }, + }, +}; + +void test_enc_dec() +{ + int i; + for (i = 0; i < ARRAY_SIZE(tests); i++) { + void *loop_ctx = talloc_named_const(ctx, 0, "loop"); + int rc; + const struct osmo_pfcp_msg *orig = &tests[i]; + struct osmo_pfcp_msg parsed = {}; + struct msgb *msg; + struct osmo_gtlv_load tlv; + + printf("\n=== start %s[%d]\n", __func__, i); + printf("encoding: %s\n", osmo_pfcp_message_type_str(orig->h.message_type)); + printf("%s\n", osmo_pfcp_msg_to_str_c(loop_ctx, orig)); + msg = msgb_alloc(1024, __func__); + rc = osmo_pfcp_msg_encode(msg, orig); + printf("osmo_pfcp_msg_encode() rc = %d\n", rc); + printf("%s.\n", osmo_hexdump(msg->data, msg->len)); + + rc = osmo_pfcp_msg_decode_header(&tlv, &parsed, msg); + printf("osmo_pfcp_msg_decode_header() rc = %d\n", rc); + if (rc != msgb_length(msg)) { + printf("ERROR: expected rc = %d\n", msgb_length(msg)); + exit(1); + } else { + printf("rc == msgb_length()\n"); + } + + rc = osmo_pfcp_msg_decode_tlv(&parsed, &tlv); + printf("osmo_pfcp_msg_decode_tlv() rc = %d\n", rc); + + if (strcmp(osmo_pfcp_msg_to_str_c(loop_ctx, orig), + osmo_pfcp_msg_to_str_c(loop_ctx, &parsed))) { + printf(" ERROR: parsed != orig\n"); + printf(" orig: %s\n", + osmo_pfcp_msg_to_str_c(loop_ctx, orig)); + printf(" parsed: %s\n", + osmo_pfcp_msg_to_str_c(loop_ctx, &parsed)); + exit(1); + } else { + printf("parsed == orig\n"); + } + + msgb_free(msg); + printf("=== end %s[%d]\n", __func__, i); + talloc_free(loop_ctx); + } +} + +int main() +{ + ctx = talloc_named_const(NULL, 0, "pfcp_test"); + msgb_talloc_ctx_init(ctx, 0); + + test_enc_dec(); + + talloc_free(ctx); + return 0; +} |