diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 46997c277322179c9398e1b4e7dad56c56a61a1c..350dae86a669f299ea383aeece1c0ce480c03ae2 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -274,6 +274,7 @@ install_asn1c_from_source(){ patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0 >> /tmp/log_compile_asn1c patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0 >> /tmp/log_compile_asn1c patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0 >> /tmp/log_compile_asn1c + patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 >> /tmp/log_compile_asn1c ./configure make > /tmp/log_compile_asn1c 2>&1 $SUDO make install diff --git a/cmake_targets/tools/build_test_epc_tools b/cmake_targets/tools/build_test_epc_tools index db49fa017b629d4c0fa7fd92d316b97758895a5e..b67cf158109f7c3b24721598552766b39b840ff5 100755 --- a/cmake_targets/tools/build_test_epc_tools +++ b/cmake_targets/tools/build_test_epc_tools @@ -141,9 +141,14 @@ function main() compilations \ epc_test test_epc_generate_scenario \ test_epc_generate_scenario $dbin/test_epc_generate_scenario + compilations \ epc_test test_epc_play_scenario \ test_epc_play_scenario $dbin/test_epc_play_scenario + + $SUDO cp -upv test_epc_generate_scenario /usr/local/bin + $SUDO cp -upv test_epc_play_scenario /usr/local/bin + $SUDO cp -upv $OPENAIR_DIR/openair3/TEST/EPC_TEST/mme_test_s1_pcap2pdml /usr/local/bin } diff --git a/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 b/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 new file mode 100644 index 0000000000000000000000000000000000000000..cf3553c362d25584cfb73d0750fd002cd3960019 --- /dev/null +++ b/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 @@ -0,0 +1,1030 @@ +--- ./asn1c/unber.c 2015-12-03 09:43:33.959009150 +0100 ++++ ./asn1c/unber.c 2015-11-30 13:20:40.751264003 +0100 +@@ -779,4 +779,6 @@ + + asn_enc_rval_t OCTET_STRING_encode_aper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *cts, void *sptr, asn_per_outp_t *po) { asn_enc_rval_t er = { 0, 0, 0 }; (void)td; (void)cts; (void)sptr; (void)po; return er; } + ++long OCTET_STRING_compare(asn_TYPE_descriptor_t *td1, void *sptr1, asn_TYPE_descriptor_t *td2, void *sptr2) { (void)td1; (void)sptr1; (void)td2; (void)sptr2; return 0; } ++ + size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size) { (void)chunk_buf; (void)chunk_size; return 0; } +--- ./libasn1compiler/asn1c_C.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./libasn1compiler/asn1c_C.c 2015-11-30 14:29:33.027259725 +0100 +@@ -1082,6 +1082,8 @@ + enum tvm_compat tv_mode; + enum etd_spec etd_spec; + char *p; ++ char tmp_buf[512]; ++ int i = 0; + + if(arg->embed) { + enum tnfmt tnfmt = TNF_CTYPE; +@@ -1243,7 +1245,8 @@ + OUT("td->uper_decoder = asn_DEF_%s.uper_decoder;\n", type_name); + OUT("td->uper_encoder = asn_DEF_%s.uper_encoder;\n", type_name); + OUT("td->aper_decoder = asn_DEF_%s.aper_decoder;\n", type_name); +- OUT("td->aper_encoder = asn_DEF_%s.aper_encoder;\n", type_name); ++ OUT("td->aper_encoder = asn_DEF_%s.aper_encoder;\n", type_name); ++ OUT("td->compare = asn_DEF_%s.compare;\n", type_name); + if(!terminal && !tags_count) { + OUT("/* The next four lines are here because of -fknown-extern-type */\n"); + OUT("td->tags = asn_DEF_%s.tags;\n", type_name); +@@ -1413,6 +1416,49 @@ + OUT("}\n"); + OUT("\n"); + ++ ++ i = 0; ++ while ((p[i] != '_') && (i < sizeof(tmp_buf))) { ++ tmp_buf[i] = p[i]; ++ i++; ++ } ++ tmp_buf[i] = '\0'; ++ // hack, only for s1ap ++ if ((strcmp("S1ap", tmp_buf) == 0) || (strcmp("X2ap", tmp_buf) == 0)) ++ OUT("#include \"%s-ProtocolIE-ID.h\"\n", tmp_buf); ++ ++ ++ p = MKID(expr); ++ if(HIDE_INNER_DEFS) OUT("static "); ++ OUT("long\n"); ++ OUT("%s", p); ++ if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index); ++ OUT("_compare(asn_TYPE_descriptor_t *td1,\n"); ++ i = 0; ++ while ((p[i] != '_') && (i < sizeof(tmp_buf))) { ++ tmp_buf[i] = p[i]; ++ i++; ++ } ++ tmp_buf[i] = '\0'; ++ strcat(tmp_buf,"_ProtocolIE_ID_id_"); ++ strcat(tmp_buf,&p[++i]); ++ INDENTED( ++ OUT("\tvoid *structure1,\n"); ++ OUT("\tasn_TYPE_descriptor_t *td2,\n"); ++ OUT("\tvoid *structure2) {\n"); ++ OUT("long rv = 0;\n"); ++ OUT("%s_%d_inherit_TYPE_descriptor(td1);\n", ++ p, expr->_type_unique_index); ++ OUT("%s_%d_inherit_TYPE_descriptor(td2);\n", ++ p, expr->_type_unique_index); ++ OUT("rv = td1->compare(td1, structure1, td2, structure2);\n"); ++ if ((strcmp("S1ap", tmp_buf) == 0) || (strcmp("X2ap", tmp_buf) == 0)) ++ OUT("if (rv) { rv = (rv << 8); rv |= %s;}\n", tmp_buf); ++ OUT("return rv;\n"); ++ ); ++ OUT("}\n"); ++ OUT("\n"); ++ + p = MKID(expr); + + if(HIDE_INNER_DEFS) OUT("static "); +@@ -1450,7 +1496,8 @@ + OUT("per_type_decoder_f %s_decode_uper;\n", p); + OUT("per_type_encoder_f %s_encode_uper;\n", p); + OUT("per_type_decoder_f %s_decode_aper;\n", p); +- OUT("per_type_encoder_f %s_encode_aper;\n", p); ++ OUT("per_type_encoder_f %s_encode_aper;\n", p); ++ OUT("type_compare_f %s_compare;\n", p); + } + } + +@@ -2501,6 +2548,7 @@ + OUT("0, 0,\t/* No APER support, " + "use \"-gen-PER\" to enable */\n"); + } ++ FUNCREF(compare); + + if(!terminal || terminal->expr_type == ASN_CONSTR_CHOICE) { + //if(expr->expr_type == ASN_CONSTR_CHOICE) { +--- ./skeletons/ANY.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/ANY.c 2015-11-26 14:40:56.547616803 +0100 +@@ -24,7 +24,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + 0, 0, 0, 0, + 0, /* No PER visible constraints */ +--- ./skeletons/BIT_STRING.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/BIT_STRING.c 2015-11-26 14:41:50.159616747 +0100 +@@ -30,7 +30,8 @@ + OCTET_STRING_decode_uper, /* Unaligned PER decoder */ + OCTET_STRING_encode_uper, /* Unaligned PER encoder */ + OCTET_STRING_decode_aper, /* Aligned PER decoder */ +- OCTET_STRING_encode_aper, /* Aligned PER encoder */ ++ OCTET_STRING_encode_aper, /* Aligned PER encoder */ ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BIT_STRING_tags, + sizeof(asn_DEF_BIT_STRING_tags) +--- ./skeletons/BMPString.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/BMPString.c 2015-11-26 14:42:08.487616728 +0100 +@@ -36,7 +36,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, /* Aligned PER decoder */ +- OCTET_STRING_encode_aper, /* Aligned PER encoder */ ++ OCTET_STRING_encode_aper, /* Aligned PER encoder */ ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BMPString_tags, + sizeof(asn_DEF_BMPString_tags) +--- ./skeletons/BOOLEAN.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/BOOLEAN.c 2015-11-30 13:16:30.275264262 +0100 +@@ -25,7 +25,8 @@ + BOOLEAN_decode_uper, /* Unaligned PER decoder */ + BOOLEAN_encode_uper, /* Unaligned PER encoder */ + BOOLEAN_decode_aper, /* Aligned PER decoder */ +- BOOLEAN_encode_aper, /* Aligned PER encoder */ ++ BOOLEAN_encode_aper, /* Aligned PER encoder */ ++ BOOLEAN_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BOOLEAN_tags, + sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]), +@@ -326,3 +327,21 @@ + + _ASN_ENCODED_OK(er); + } ++ ++long ++BOOLEAN_compare(asn_TYPE_descriptor_t *td1, ++ void *sptr1, asn_TYPE_descriptor_t *td2, void *sptr2) { ++ const BOOLEAN_t *st1 = (const BOOLEAN_t *)sptr1; ++ const BOOLEAN_t *st2 = (const BOOLEAN_t *)sptr2; ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ return (*st1 != *st2); ++} ++ +--- ./skeletons/BOOLEAN.h 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/BOOLEAN.h 2015-11-26 12:46:58.491623882 +0100 +@@ -30,6 +30,7 @@ + per_type_encoder_f BOOLEAN_encode_uper; + per_type_decoder_f BOOLEAN_decode_aper; + per_type_encoder_f BOOLEAN_encode_aper; ++type_compare_f BOOLEAN_compare; + + #ifdef __cplusplus + } +--- ./skeletons/compare.h 1970-01-01 01:00:00.000000000 +0100 ++++ ./skeletons/compare.h 2015-11-30 13:15:56.415264297 +0100 +@@ -0,0 +1,27 @@ ++/*- ++ * Eurecom 2015. ++ */ ++#ifndef _COMPARE_H_ ++#define _COMPARE_H_ ++ ++#include <asn_application.h> ++#include <per_support.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct asn_TYPE_descriptor_s; /* Forward declaration */ ++ ++typedef long (type_compare_f)( ++ struct asn_TYPE_descriptor_s *type_descriptor1, ++ void *struct_ptr1, ++ struct asn_TYPE_descriptor_s *type_descriptor2, ++ void *struct_ptr2 ++); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _COMPARE_H_ */ +--- ./skeletons/constr_CHOICE.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/constr_CHOICE.c 2015-11-30 13:16:49.007264243 +0100 +@@ -1272,3 +1272,57 @@ + assert(pres_size != sizeof(int)); + } + } ++ ++long ++CHOICE_compare(asn_TYPE_descriptor_t *td1, void *sptr1, asn_TYPE_descriptor_t *td2, void *sptr2) ++{ ++ asn_CHOICE_specifics_t *specs1 = (asn_CHOICE_specifics_t *)td1->specifics; ++ asn_CHOICE_specifics_t *specs2 = (asn_CHOICE_specifics_t *)td2->specifics; ++ int present1; ++ int present2; ++ ++ if ((!sptr1) && (!sptr2)) return 0; ++ if (!sptr1) return -1; ++ if (!sptr2) return -1; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ ++ /* ++ * Figure out which CHOICE element is encoded. ++ */ ++ present1 = _fetch_present_idx(sptr1, specs1->pres_offset,specs1->pres_size); ++ // same specs ++ present2 = _fetch_present_idx(sptr2, specs2->pres_offset,specs2->pres_size); ++ ++ if (td1->elements_count != td2->elements_count) return -1; ++ if (present1 != present2) return -1; ++ if(present1 > 0 && present1 <= td1->elements_count) { ++ asn_TYPE_member_t *elm1 = &td1->elements[present1-1]; ++ asn_TYPE_member_t *elm2 = &td2->elements[present2-1]; ++ const void *memb_ptr1; ++ const void *memb_ptr2; ++ ++ if((elm1->flags & ATF_POINTER) && (elm1->flags & ATF_POINTER)){ ++ memb_ptr1 = *(const void * const *)((const char *)sptr1 + elm1->memb_offset); ++ memb_ptr2 = *(const void * const *)((const char *)sptr2 + elm2->memb_offset); ++ if((!memb_ptr1) && (!memb_ptr2)) return -1; ++ if (!memb_ptr1) return -1; ++ if (!memb_ptr2) return -1; ++ } else if (!(elm1->flags & ATF_POINTER) && !(elm1->flags & ATF_POINTER)){ ++ memb_ptr1 = (const void *)((const char *)sptr1 + elm1->memb_offset); ++ memb_ptr2 = (const void *)((const char *)sptr2 + elm2->memb_offset); ++ } else { ++ return -1; ++ } ++ return elm1->type->compare(elm1->type, memb_ptr1, elm2->type, memb_ptr2); ++ } ++ return 0; ++} +--- ./skeletons/constr_CHOICE.h 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/constr_CHOICE.h 2015-11-26 14:43:57.647616615 +0100 +@@ -39,7 +39,7 @@ + /* + * A set specialized functions dealing with the CHOICE type. + */ +-asn_struct_free_f CHOICE_free; ++asn_struct_free_f CHOICE_free; + asn_struct_print_f CHOICE_print; + asn_constr_check_f CHOICE_constraint; + ber_type_decoder_f CHOICE_decode_ber; +@@ -50,7 +50,8 @@ + per_type_encoder_f CHOICE_encode_uper; + per_type_decoder_f CHOICE_decode_aper; + per_type_encoder_f CHOICE_encode_aper; +-asn_outmost_tag_f CHOICE_outmost_tag; ++type_compare_f CHOICE_compare; ++asn_outmost_tag_f CHOICE_outmost_tag; + + #ifdef __cplusplus + } +--- ./skeletons/constr_SEQUENCE.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/constr_SEQUENCE.c 2015-11-30 13:17:33.871264196 +0100 +@@ -1761,3 +1761,50 @@ + + _ASN_ENCODED_OK(er); + } ++ ++long ++SEQUENCE_compare(asn_TYPE_descriptor_t *td1, void *sptr1, asn_TYPE_descriptor_t *td2, void *sptr2) { ++ int edx; ++ int ret; ++ ++ if((!sptr1) && (!sptr2)) return -1; ++ if(!sptr1) return -1; ++ if(!sptr2) return -1; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ ++ if (td1->elements_count != td2->elements_count) return -1; ++ ++ for(edx = 0; edx < td1->elements_count; edx++) { ++ asn_TYPE_member_t *elm1 = &td1->elements[edx]; ++ asn_TYPE_member_t *elm2 = &td1->elements[edx]; ++ const void *memb_ptr1; ++ const void *memb_ptr2; ++ ++ if(elm1->flags & ATF_POINTER) { ++ memb_ptr1 = *(const void * const *)((const char *)sptr1 + elm1->memb_offset); ++ memb_ptr2 = *(const void * const *)((const char *)sptr2 + elm2->memb_offset); ++ if((!memb_ptr1) && (!memb_ptr2)) { ++ if(elm1->optional) continue; ++ } ++ if (!memb_ptr1) return -1; ++ if (!memb_ptr2) return -1; ++ } else { ++ memb_ptr1 = (const void *)((const char *)sptr1 + elm1->memb_offset); ++ memb_ptr2 = (const void *)((const char *)sptr2 + elm2->memb_offset); ++ } ++ ++ /* Compare the member itself */ ++ ret = elm1->type->compare(elm1->type, memb_ptr1, elm2->type, memb_ptr2); ++ if(ret) return ret; ++ } ++ return 0; ++} +--- ./skeletons/constr_SEQUENCE.h 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/constr_SEQUENCE.h 2015-11-26 14:48:14.123616350 +0100 +@@ -54,6 +54,7 @@ + per_type_encoder_f SEQUENCE_encode_uper; + per_type_decoder_f SEQUENCE_decode_aper; + per_type_encoder_f SEQUENCE_encode_aper; ++type_compare_f SEQUENCE_compare; + + #ifdef __cplusplus + } +--- ./skeletons/constr_SEQUENCE_OF.h 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/constr_SEQUENCE_OF.h 2015-11-26 15:05:25.399615282 +0100 +@@ -22,7 +22,8 @@ + #define SEQUENCE_OF_decode_ber SET_OF_decode_ber + #define SEQUENCE_OF_decode_xer SET_OF_decode_xer + #define SEQUENCE_OF_decode_uper SET_OF_decode_uper +-#define SEQUENCE_OF_decode_aper SET_OF_decode_aper ++#define SEQUENCE_OF_decode_aper SET_OF_decode_aper ++#define SEQUENCE_OF_compare SET_OF_compare + der_type_encoder_f SEQUENCE_OF_encode_der; + xer_type_encoder_f SEQUENCE_OF_encode_xer; + per_type_encoder_f SEQUENCE_OF_encode_uper; +--- ./skeletons/constr_SET.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/constr_SET.c 2015-11-30 13:17:49.903264180 +0100 +@@ -1108,7 +1108,7 @@ + } + } + +-int ++long + SET_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + int edx; +--- ./skeletons/constr_SET.h 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/constr_SET.h 2015-11-26 14:49:09.243616293 +0100 +@@ -56,6 +56,7 @@ + per_type_decoder_f SET_decode_aper; + per_type_encoder_f SET_encode_uper; + per_type_encoder_f SET_encode_aper; ++type_compare_f SET_compare; + + /*********************** + * Some handy helpers. * +--- ./skeletons/constr_SET_OF.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/constr_SET_OF.c 2015-11-30 13:17:42.099264188 +0100 +@@ -1039,3 +1039,46 @@ + rv.consumed = 0; + return rv; + } ++ ++long ++SET_OF_compare(asn_TYPE_descriptor_t *td1, void *sptr1, asn_TYPE_descriptor_t *td2, void *sptr2) ++{ ++ asn_TYPE_member_t *elm1 = td1->elements; ++ asn_TYPE_member_t *elm2 = td2->elements; ++ const asn_anonymous_set_ *list1 = _A_CSET_FROM_VOID(sptr1); ++ const asn_anonymous_set_ *list2 = _A_CSET_FROM_VOID(sptr2); ++ int ret; ++ int i; ++ ++ if((!sptr1) && !(sptr2)) return 0; ++ if(!sptr1) return -1; ++ if(!sptr2) return -1; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ ++ if (td1->elements_count != td2->elements_count) return -1; ++ ++ ++ if (list1->count != list2->count ) return -1; ++ ++ for(i = 0; i < list1->count; i++) { ++ const void *memb_ptr1 = list1->array[i]; ++ const void *memb_ptr2 = list2->array[i]; ++ if ((!memb_ptr1) & (!memb_ptr2)) continue; ++ if(!memb_ptr1) return -1; ++ if(!memb_ptr2) return -1; ++ ++ ret = elm1->type->compare(elm1->type, memb_ptr1, elm2->type, memb_ptr2); ++ if(ret) return ret; ++ } ++ ++ return 0; ++} +--- ./skeletons/constr_SET_OF.h 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/constr_SET_OF.h 2015-11-26 14:48:45.067616318 +0100 +@@ -36,6 +36,7 @@ + per_type_encoder_f SET_OF_encode_uper; + per_type_decoder_f SET_OF_decode_aper; + per_type_encoder_f SET_OF_encode_aper; ++type_compare_f SET_OF_compare; + + #ifdef __cplusplus + } +--- ./skeletons/constr_TYPE.h 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/constr_TYPE.h 2015-11-26 15:28:05.495613874 +0100 +@@ -41,7 +41,8 @@ + #include <xer_encoder.h> /* Encoder into XER (XML, text) */ + #include <per_decoder.h> /* Packet Encoding Rules decoder */ + #include <per_encoder.h> /* Packet Encoding Rules encoder */ +-#include <constraints.h> /* Subtype constraints support */ ++#include <constraints.h> /* Subtype constraints support */ ++#include <compare.h> /* Comparison */ + + /* + * Free the structure according to its specification. +@@ -101,6 +102,7 @@ + per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */ + per_type_decoder_f *aper_decoder; /* Aligned PER decoder */ + per_type_encoder_f *aper_encoder; /* Aligned PER encoder */ ++ type_compare_f *compare; /* Comparison between 2 instances */ + + /*********************************************************************** + * Internally useful members. Not to be used by applications directly. * +--- ./skeletons/ENUMERATED.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/ENUMERATED.c 2015-11-30 13:18:05.399264164 +0100 +@@ -27,7 +27,8 @@ + ENUMERATED_decode_uper, /* Unaligned PER decoder */ + ENUMERATED_encode_uper, /* Unaligned PER encoder */ + ENUMERATED_decode_aper, /* Aligned PER decoder */ +- ENUMERATED_encode_aper, /* Aligned PER encoder */ ++ ENUMERATED_encode_aper, /* Aligned PER encoder */ ++ ENUMERATED_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ENUMERATED_tags, + sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]), +@@ -103,3 +104,22 @@ + + return NativeEnumerated_encode_aper(td, constraints, &value, po); + } ++ ++long ++ENUMERATED_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ ENUMERATED_t *st1 = (ENUMERATED_t *)sptr1; ++ ENUMERATED_t *st2 = (ENUMERATED_t *)sptr2; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ return (*st1 != *st2); ++} ++ +--- ./skeletons/ENUMERATED.h 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/ENUMERATED.h 2015-11-26 12:46:35.523623906 +0100 +@@ -19,6 +19,7 @@ + per_type_encoder_f ENUMERATED_encode_uper; + per_type_decoder_f ENUMERATED_decode_aper; + per_type_encoder_f ENUMERATED_encode_aper; ++type_compare_f ENUMERATED_compare; + + #ifdef __cplusplus + } +--- ./skeletons/file-dependencies 2015-12-03 09:43:33.731009150 +0100 ++++ ./skeletons/file-dependencies 2015-11-26 16:05:44.923611535 +0100 +@@ -39,7 +39,7 @@ + constr_SEQUENCE.h constr_SEQUENCE.c + constr_SEQUENCE_OF.h constr_SEQUENCE_OF.c asn_SEQUENCE_OF.h constr_SET_OF.h + constr_SET.h constr_SET.c +-constr_SET_OF.h constr_SET_OF.c asn_SET_OF.h ++constr_SET_OF.h constr_SET_OF.c asn_SET_OF.h compare.h + + COMMON-FILES: # THIS IS A SPECIAL SECTION + asn_application.h # Applications should include this file +--- ./skeletons/GeneralizedTime.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/GeneralizedTime.c 2015-11-26 15:09:03.899615056 +0100 +@@ -168,7 +168,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_GeneralizedTime_tags, + sizeof(asn_DEF_GeneralizedTime_tags) +--- ./skeletons/GeneralString.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/GeneralString.c 2015-11-26 14:50:11.843616228 +0100 +@@ -25,7 +25,8 @@ + OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_GeneralString_tags, + sizeof(asn_DEF_GeneralString_tags) +--- ./skeletons/GraphicString.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/GraphicString.c 2015-11-26 15:33:33.255613535 +0100 +@@ -25,7 +25,8 @@ + OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_GraphicString_tags, + sizeof(asn_DEF_GraphicString_tags) +--- ./skeletons/IA5String.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/IA5String.c 2015-11-26 14:50:44.219616194 +0100 +@@ -31,6 +31,7 @@ + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, + OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IA5String_tags, + sizeof(asn_DEF_IA5String_tags) +--- ./skeletons/INTEGER.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/INTEGER.c 2015-11-30 13:18:18.143264151 +0100 +@@ -35,6 +35,7 @@ + INTEGER_decode_aper, + INTEGER_encode_aper, + #endif /* ASN_DISABLE_PER_SUPPORT */ ++ INTEGER_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_INTEGER_tags, + sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), +@@ -1501,3 +1502,20 @@ + } + + ++long ++INTEGER_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ INTEGER_t *st1 = (INTEGER_t *)sptr1; ++ INTEGER_t *st2 = (INTEGER_t *)sptr2; ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ if (st1->size != st2->size) return -1; ++ return memcmp(st1->buf, st2->buf, st1->size); ++} +--- ./skeletons/INTEGER.h 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/INTEGER.h 2015-11-26 12:50:41.551623651 +0100 +@@ -43,6 +43,7 @@ + per_type_encoder_f INTEGER_encode_uper; + per_type_decoder_f INTEGER_decode_aper; + per_type_encoder_f INTEGER_encode_aper; ++type_compare_f INTEGER_compare; + + /*********************************** + * Some handy conversion routines. * +--- ./skeletons/ISO646String.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/ISO646String.c 2015-11-26 12:55:48.327623333 +0100 +@@ -30,7 +30,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ISO646String_tags, + sizeof(asn_DEF_ISO646String_tags) +--- ./skeletons/Makefile.am 2015-12-03 09:43:33.715009150 +0100 ++++ ./skeletons/Makefile.am 2015-11-26 15:28:55.887613822 +0100 +@@ -50,7 +50,7 @@ + ber_decoder.c ber_decoder.h \ + ber_tlv_length.c ber_tlv_length.h \ + ber_tlv_tag.c ber_tlv_tag.h \ +- constr_CHOICE.c constr_CHOICE.h \ ++ comparison.h constr_CHOICE.c constr_CHOICE.h \ + constr_SEQUENCE.c constr_SEQUENCE.h \ + constr_SEQUENCE_OF.c constr_SEQUENCE_OF.h \ + constr_SET.c constr_SET.h \ +--- ./skeletons/NativeEnumerated.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/NativeEnumerated.c 2015-11-30 13:18:32.015264136 +0100 +@@ -31,7 +31,8 @@ + NativeEnumerated_decode_uper, + NativeEnumerated_encode_uper, + NativeEnumerated_decode_aper, +- NativeEnumerated_encode_aper, ++ NativeEnumerated_encode_aper, ++ NativeEnumerated_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeEnumerated_tags, + sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), +@@ -335,3 +336,25 @@ + + _ASN_ENCODED_OK(er); + } ++ ++long ++NativeEnumerated_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ const asn_INTEGER_enum_map_t *a = sptr1; ++ const asn_INTEGER_enum_map_t *b = sptr2; ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ ++ if(a->nat_value == b->nat_value) ++ return 0; ++ if(a->nat_value < b->nat_value) ++ return -1; ++ return 1; ++} +--- ./skeletons/NativeEnumerated.h 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/NativeEnumerated.h 2015-11-26 14:51:43.315616133 +0100 +@@ -26,6 +26,7 @@ + per_type_encoder_f NativeEnumerated_encode_uper; + per_type_decoder_f NativeEnumerated_decode_aper; + per_type_encoder_f NativeEnumerated_encode_aper; ++type_compare_f NativeEnumerated_compare; + + #ifdef __cplusplus + } +--- ./skeletons/NativeInteger.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/NativeInteger.c 2015-11-30 13:18:39.887264128 +0100 +@@ -32,7 +32,8 @@ + NativeInteger_decode_uper, /* Unaligned PER decoder */ + NativeInteger_encode_uper, /* Unaligned PER encoder */ + NativeInteger_decode_aper, /* Aligned PER decoder */ +- NativeInteger_encode_aper, /* Aligned PER encoder */ ++ NativeInteger_encode_aper, /* Aligned PER encoder */ ++ NativeInteger_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeInteger_tags, + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), +@@ -410,3 +411,20 @@ + } + } + ++ ++long ++NativeInteger_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ const long *native1 = (const long *)sptr1; ++ const long *native2 = (const long *)sptr2; ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ return (*native1 != *native2); ++} +--- ./skeletons/NativeInteger.h 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/NativeInteger.h 2015-11-26 14:52:13.931616101 +0100 +@@ -31,6 +31,7 @@ + per_type_encoder_f NativeInteger_encode_uper; + per_type_decoder_f NativeInteger_decode_aper; + per_type_encoder_f NativeInteger_encode_aper; ++type_compare_f NativeInteger_compare; + + #ifdef __cplusplus + } +--- ./skeletons/NativeReal.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/NativeReal.c 2015-11-30 13:18:46.655264121 +0100 +@@ -33,7 +33,8 @@ + NativeReal_decode_uper, + NativeReal_encode_uper, + NativeReal_decode_aper, +- NativeReal_encode_aper, ++ NativeReal_encode_aper, ++ NativeReal_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeReal_tags, + sizeof(asn_DEF_NativeReal_tags) / sizeof(asn_DEF_NativeReal_tags[0]), +@@ -405,3 +406,21 @@ + } + } + ++long ++NativeReal_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ REAL_t *st1 = (REAL_t *)sptr1; ++ REAL_t *st2 = (REAL_t *)sptr2; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ if (st1->size != st2->size) return -1; ++ return memcmp(st1->buf, st2->buf, st1->size); ++} +--- ./skeletons/NativeReal.h 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/NativeReal.h 2015-11-26 14:31:12.631617407 +0100 +@@ -29,6 +29,7 @@ + per_type_encoder_f NativeReal_encode_uper; + per_type_decoder_f NativeReal_decode_aper; + per_type_encoder_f NativeReal_encode_aper; ++type_compare_f NativeReal_compare; + + #ifdef __cplusplus + } +--- ./skeletons/NULL.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/NULL.c 2015-11-30 13:18:53.047264114 +0100 +@@ -26,7 +26,8 @@ + NULL_decode_uper, /* Unaligned PER decoder */ + NULL_encode_uper, /* Unaligned PER encoder */ + NULL_decode_aper, /* Aligned PER decoder */ +- NULL_encode_aper, /* Aligned PER encoder */ ++ NULL_encode_aper, /* Aligned PER encoder */ ++ NULL_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NULL_tags, + sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), +@@ -192,3 +193,10 @@ + er.encoded = 0; + _ASN_ENCODED_OK(er); + } ++ ++long ++NULL_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ ++ return 0; ++} +--- ./skeletons/NULL.h 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/NULL.h 2015-11-26 14:53:03.875616050 +0100 +@@ -27,6 +27,7 @@ + per_type_encoder_f NULL_encode_uper; + per_type_decoder_f NULL_decode_aper; + per_type_encoder_f NULL_encode_aper; ++type_compare_f NULL_compare; + + #ifdef __cplusplus + } +--- ./skeletons/NumericString.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/NumericString.c 2015-11-26 14:40:39.407616820 +0100 +@@ -50,7 +50,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NumericString_tags, + sizeof(asn_DEF_NumericString_tags) +--- ./skeletons/ObjectDescriptor.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/ObjectDescriptor.c 2015-11-26 14:55:46.227615882 +0100 +@@ -25,7 +25,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ObjectDescriptor_tags, + sizeof(asn_DEF_ObjectDescriptor_tags) +--- ./skeletons/OBJECT_IDENTIFIER.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/OBJECT_IDENTIFIER.c 2015-11-26 14:55:13.311615916 +0100 +@@ -28,7 +28,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_OBJECT_IDENTIFIER_tags, + sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) +--- ./skeletons/OCTET_STRING.c 2015-12-03 09:43:33.975009150 +0100 ++++ ./skeletons/OCTET_STRING.c 2015-11-30 13:19:18.271264088 +0100 +@@ -37,7 +37,8 @@ + OCTET_STRING_decode_uper, /* Unaligned PER decoder */ + OCTET_STRING_encode_uper, /* Unaligned PER encoder */ + OCTET_STRING_decode_aper, /* Aligned PER decoder */ +- OCTET_STRING_encode_aper, /* Aligned PER encoder */ ++ OCTET_STRING_encode_aper, /* Aligned PER encoder */ ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_OCTET_STRING_tags, + sizeof(asn_DEF_OCTET_STRING_tags) +@@ -2160,3 +2161,21 @@ + return st; + } + ++long ++OCTET_STRING_compare(asn_TYPE_descriptor_t *td1, ++ void *sptr1, asn_TYPE_descriptor_t *td2, void *sptr2) { ++ OCTET_STRING_t *st1 = (OCTET_STRING_t *)sptr1; ++ OCTET_STRING_t *st2 = (OCTET_STRING_t *)sptr2; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ if (st1->size != st2->size) return -1; ++ return memcmp(st1->buf, st2->buf, st1->size); ++} +--- ./skeletons/OCTET_STRING.h 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/OCTET_STRING.h 2015-11-26 12:56:15.259623305 +0100 +@@ -34,6 +34,7 @@ + per_type_encoder_f OCTET_STRING_encode_uper; + per_type_decoder_f OCTET_STRING_decode_aper; + per_type_encoder_f OCTET_STRING_encode_aper; ++type_compare_f OCTET_STRING_compare; + + /****************************** + * Handy conversion routines. * +--- ./skeletons/PrintableString.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/PrintableString.c 2015-11-26 14:56:09.787615857 +0100 +@@ -60,7 +60,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_PrintableString_tags, + sizeof(asn_DEF_PrintableString_tags) +--- ./skeletons/REAL.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/REAL.c 2015-11-30 13:19:27.671264079 +0100 +@@ -46,7 +46,8 @@ + REAL_decode_uper, + REAL_encode_uper, + REAL_decode_aper, +- REAL_encode_aper, ++ REAL_encode_aper, ++ REAL_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_REAL_tags, + sizeof(asn_DEF_REAL_tags) / sizeof(asn_DEF_REAL_tags[0]), +@@ -741,3 +742,23 @@ + + return 0; + } ++ ++ ++long ++REAL_compare(asn_TYPE_descriptor_t *td1, void *sptr1, ++ asn_TYPE_descriptor_t *td2, void *sptr2) { ++ REAL_t *st1 = (REAL_t *)sptr1; ++ REAL_t *st2 = (REAL_t *)sptr2; ++ ++ if ((td1) && (td2)) { ++ if ((td1->name) && (td2->name)) { ++ if (strcmp(td1->name, td2->name)) return -1; ++ } else { ++ if ((td1->xml_tag) && (td2->xml_tag)) { ++ if (strcmp(td1->xml_tag, td2->xml_tag)) return -1; ++ } ++ } ++ } ++ if (st1->size != st2->size) return -1; ++ return memcmp(st1->buf, st2->buf, st1->size); ++} +--- ./skeletons/REAL.h 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/REAL.h 2015-11-26 13:00:46.183623025 +0100 +@@ -23,6 +23,7 @@ + per_type_encoder_f REAL_encode_uper; + per_type_decoder_f REAL_decode_aper; + per_type_encoder_f REAL_encode_aper; ++type_compare_f REAL_compare; + + /*********************************** + * Some handy conversion routines. * +--- ./skeletons/RELATIVE-OID.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/RELATIVE-OID.c 2015-11-26 14:56:31.703615834 +0100 +@@ -29,7 +29,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_RELATIVE_OID_tags, + sizeof(asn_DEF_RELATIVE_OID_tags) +--- ./skeletons/T61String.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/T61String.c 2015-11-26 14:57:07.235615798 +0100 +@@ -25,7 +25,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_T61String_tags, + sizeof(asn_DEF_T61String_tags) +--- ./skeletons/TeletexString.c 2015-12-03 09:43:33.963009150 +0100 ++++ ./skeletons/TeletexString.c 2015-11-26 14:57:17.643615787 +0100 +@@ -25,7 +25,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_TeletexString_tags, + sizeof(asn_DEF_TeletexString_tags) +--- ./skeletons/UniversalString.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/UniversalString.c 2015-11-26 14:57:29.015615775 +0100 +@@ -36,7 +36,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_UniversalString_tags, + sizeof(asn_DEF_UniversalString_tags) +--- ./skeletons/UTCTime.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/UTCTime.c 2015-11-26 14:57:44.127615759 +0100 +@@ -41,7 +41,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_UTCTime_tags, + sizeof(asn_DEF_UTCTime_tags) +--- ./skeletons/UTF8String.c 2015-12-03 09:43:33.959009150 +0100 ++++ ./skeletons/UTF8String.c 2015-11-26 14:06:54.563618917 +0100 +@@ -27,6 +27,7 @@ + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, + OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_UTF8String_tags, + sizeof(asn_DEF_UTF8String_tags) +--- ./skeletons/VideotexString.c 2015-12-03 09:43:33.967009150 +0100 ++++ ./skeletons/VideotexString.c 2015-11-26 14:07:06.139618905 +0100 +@@ -25,7 +25,8 @@ + OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_VideotexString_tags, + sizeof(asn_DEF_VideotexString_tags) +--- ./skeletons/VisibleString.c 2015-12-03 09:43:33.971009150 +0100 ++++ ./skeletons/VisibleString.c 2015-11-26 14:07:15.283618895 +0100 +@@ -30,7 +30,8 @@ + OCTET_STRING_decode_uper, + OCTET_STRING_encode_uper, + OCTET_STRING_decode_aper, +- OCTET_STRING_encode_aper, ++ OCTET_STRING_encode_aper, ++ OCTET_STRING_compare, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_VisibleString_tags, + sizeof(asn_DEF_VisibleString_tags) diff --git a/openair3/TEST/EPC_TEST/play_scenario.c b/openair3/TEST/EPC_TEST/play_scenario.c index 9a9cb881b1ed39598e72c5b31e8172d8268ef59a..1aab21642829949e6178e9ce19663cc966d9d4b7 100644 --- a/openair3/TEST/EPC_TEST/play_scenario.c +++ b/openair3/TEST/EPC_TEST/play_scenario.c @@ -331,18 +331,18 @@ int et_compare_et_ip_to_net_ip_address(const et_ip_t * const ip, const net_ip_ad switch (ip->address_family) { case AF_INET: if (net_ip->ipv4) { - S1AP_DEBUG("%s(%s,%s)=%d\n",__FUNCTION__,ip->str, net_ip->ipv4_address, strcmp(ip->str, net_ip->ipv4_address)); + //S1AP_DEBUG("%s(%s,%s)=%d\n",__FUNCTION__,ip->str, net_ip->ipv4_address, strcmp(ip->str, net_ip->ipv4_address)); return strcmp(ip->str, net_ip->ipv4_address); } - S1AP_DEBUG("%s(%s,%s)=-1 (IP version (4) not matching)\n",__FUNCTION__,ip->str, net_ip->ipv4_address); + //S1AP_DEBUG("%s(%s,%s)=-1 (IP version (4) not matching)\n",__FUNCTION__,ip->str, net_ip->ipv4_address); return -1; break; case AF_INET6: if (net_ip->ipv6) { - S1AP_DEBUG("%s(%s,%s)=%d\n",__FUNCTION__,ip->str, net_ip->ipv4_address, strcmp(ip->str, net_ip->ipv6_address)); + //S1AP_DEBUG("%s(%s,%s)=%d\n",__FUNCTION__,ip->str, net_ip->ipv4_address, strcmp(ip->str, net_ip->ipv6_address)); return strcmp(ip->str, net_ip->ipv6_address); } - S1AP_DEBUG("%s(%s,%s)=-1 (IP version (6) not matching)\n",__FUNCTION__,ip->str, net_ip->ipv6_address); + //S1AP_DEBUG("%s(%s,%s)=-1 (IP version (6) not matching)\n",__FUNCTION__,ip->str, net_ip->ipv6_address); return -1; break; default: diff --git a/openair3/TEST/EPC_TEST/play_scenario_fsm.c b/openair3/TEST/EPC_TEST/play_scenario_fsm.c index b6ff0de85916b0e18eb638ac83ce95756ad27586..1db9df632eec6b87bd23b5a01db05e39fc1c417f 100644 --- a/openair3/TEST/EPC_TEST/play_scenario_fsm.c +++ b/openair3/TEST/EPC_TEST/play_scenario_fsm.c @@ -87,6 +87,7 @@ void et_scenario_wait_rx_packet(et_packet_t * const packet) NULL, &packet->timer_id) < 0) { AssertFatal(0, " Can not start waiting RX event timer\n"); } + LOG_D(ENB_APP, "Waiting RX packet num %d\n", packet->packet_number); g_fsm_state = ET_FSM_STATE_WAITING_RX_EVENT; packet->status = ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING; } @@ -144,6 +145,7 @@ void et_scenario_schedule_tx_packet(et_packet_t * const packet) packet->sctp_hdr.u.data_hdr.payload.binary_stream_allocated_size, packet->sctp_hdr.u.data_hdr.stream); packet->status = ET_PACKET_STATUS_SENT; + g_scenario->next_packet = g_scenario->next_packet->next; g_fsm_state = ET_FSM_STATE_RUNNING; } break; @@ -161,8 +163,76 @@ et_fsm_state_t et_scenario_fsm_notify_event_state_running(et_event_t event) switch (event.code){ case ET_EVENT_TICK: - //TODO + while (NULL != g_scenario->next_packet) { + LOG_D(ENB_APP, "EVENT_TICK: Considering packet num %d:\n", g_scenario->next_packet->packet_number); + switch (g_scenario->next_packet->sctp_hdr.chunk_type) { + case SCTP_CID_DATA : + // no init in this scenario, may be sub-scenario + if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) { + if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) { + et_scenario_schedule_tx_packet(g_scenario->next_packet); + pthread_mutex_unlock(&g_fsm_lock); + + et_event_t continue_event; + continue_event.code = ET_EVENT_TICK; + et_scenario_fsm_notify_event(continue_event); + + return g_fsm_state; + } else if (g_scenario->next_packet->status != ET_PACKET_STATUS_SCHEDULED_FOR_SENDING) { + AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status); + } + } else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) { + if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) { + g_scenario->next_packet = g_scenario->next_packet->next; + + } else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) { + et_scenario_wait_rx_packet(g_scenario->next_packet); + pthread_mutex_unlock(&g_fsm_lock); + return g_fsm_state; + } else { + AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status); + } + } else { + AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action); + } + break; + + case SCTP_CID_INIT: + case SCTP_CID_INIT_ACK: + case SCTP_CID_HEARTBEAT: + case SCTP_CID_HEARTBEAT_ACK: + case SCTP_CID_COOKIE_ECHO: + case SCTP_CID_COOKIE_ACK: + case SCTP_CID_ECN_ECNE: + case SCTP_CID_ECN_CWR: + LOG_D(ENB_APP, "EVENT_TICK: Ignoring packet num %d SCTP CID %s\n", + g_scenario->next_packet->packet_number, + et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type)); + g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT; + g_scenario->next_packet = g_scenario->next_packet->next; + break; + + case SCTP_CID_ABORT: + case SCTP_CID_SHUTDOWN: + case SCTP_CID_SHUTDOWN_ACK: + case SCTP_CID_ERROR: + case SCTP_CID_SHUTDOWN_COMPLETE: + AssertFatal(0, "The scenario should be cleaned (packet %s cannot be processed at this time)", + et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type)); + break; + default: + LOG_D(ENB_APP, "EVENT_TICK: Ignoring packet num %d SCTP CID %s\n", + g_scenario->next_packet->packet_number, + et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type)); + g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT; + g_scenario->next_packet = g_scenario->next_packet->next; + } + } + fprintf(stderr, "No Packet found in this scenario: %s\n", g_scenario->name); + g_fsm_state = ET_FSM_STATE_NULL; + pthread_mutex_unlock(&g_fsm_lock); + return g_fsm_state; break; case ET_EVENT_RX_PACKET_TIME_OUT: AssertFatal(0, "Event ET_EVENT_RX_PACKET_TIME_OUT not handled in FSM state ET_FSM_STATE_RUNNING"); @@ -186,6 +256,7 @@ et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_tx(et_event_t event) int rv = 0; switch (event.code){ case ET_EVENT_TICK: + fprintf(stdout, "EVENT_TICK: waiting for tx event\n"); break; case ET_EVENT_RX_S1AP: @@ -202,6 +273,7 @@ et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_tx(et_event_t event) event.u.tx_timed_packet->sctp_hdr.u.data_hdr.payload.binary_stream_allocated_size, event.u.tx_timed_packet->sctp_hdr.u.data_hdr.stream); event.u.tx_timed_packet->status = ET_PACKET_STATUS_SENT; + g_scenario->next_packet = event.u.tx_timed_packet->next; g_fsm_state = ET_FSM_STATE_RUNNING; break; @@ -219,6 +291,7 @@ et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_rx(et_event_t event) int rv = 0; switch (event.code){ case ET_EVENT_TICK: + fprintf(stdout, "EVENT_TICK: waiting for rx event\n"); break; case ET_EVENT_RX_PACKET_TIME_OUT: @@ -272,7 +345,6 @@ et_fsm_state_t et_scenario_fsm_notify_event_state_connecting_s1c(et_event_t even } else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) { if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) { g_scenario->last_rx_packet = g_scenario->next_packet; - g_scenario->next_packet = g_scenario->next_packet->next; g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet; g_scenario->next_packet = g_scenario->next_packet->next; @@ -357,7 +429,6 @@ et_fsm_state_t et_scenario_fsm_notify_event_state_null(et_event_t event) } else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) { if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) { g_scenario->last_rx_packet = g_scenario->next_packet; - g_scenario->next_packet = g_scenario->next_packet->next; g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet; g_scenario->next_packet = g_scenario->next_packet->next; diff --git a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c index 336dc547d52e38dbff80d8084e3b52792c37dc5d..142ab069e93e1bdec8f59aed74f85659ba40a9cb 100644 --- a/openair3/TEST/EPC_TEST/play_scenario_s1ap.c +++ b/openair3/TEST/EPC_TEST/play_scenario_s1ap.c @@ -250,9 +250,24 @@ et_packet_t* et_build_packet_from_s1ap_data_ind(et_event_s1ap_data_ind_t * const // return 0 if packet was waited int et_scenario_set_packet_received(et_packet_t * const packet) { - int rc = 0; + et_packet_t * p = NULL; + int rc = 0; + packet->status = ET_PACKET_STATUS_RECEIVED; S1AP_DEBUG("Packet num %d received\n", packet->packet_number); + + p = g_scenario->last_rx_packet; + while (NULL != p) { + if (p->action == ET_PACKET_ACTION_S1C_RECEIVE) { + if (p->status == ET_PACKET_STATUS_RECEIVED) { + g_scenario->last_rx_packet = p; + } else { + break; + } + } + p = p->next; + } + if (packet->timer_id != 0) { rc = timer_remove(packet->timer_id); AssertFatal(rc == 0, "TODO: Debug Timer on Rx packet num %d unknown", packet->packet_number); @@ -278,6 +293,7 @@ int et_s1ap_process_rx_packet(et_event_s1ap_data_ind_t * const s1ap_data_ind) if (packet->action == ET_PACKET_ACTION_S1C_RECEIVE) { if (packet->status == ET_PACKET_STATUS_RECEIVED) { g_scenario->last_rx_packet = packet; + g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet; } else { break; } @@ -286,7 +302,7 @@ int et_s1ap_process_rx_packet(et_event_s1ap_data_ind_t * const s1ap_data_ind) } packet = g_scenario->list_packet; } else { - packet = g_scenario->last_rx_packet; + packet = g_scenario->last_rx_packet->next; } // not_found threshold may sure depend on number of mme, may be not sure on number of UE while ((NULL != packet) && (not_found < 5)) { @@ -308,8 +324,8 @@ int et_s1ap_process_rx_packet(et_event_s1ap_data_ind_t * const s1ap_data_ind) not_found += 1; packet = packet->next; } - S1AP_DEBUG("Rx packet not found in scenario:\n"); et_display_packet_sctp(&rx_packet->sctp_hdr); + AssertFatal(0, "Rx packet not found in scenario (see dump above)"); return -1; }