E2AP: moving towards a better design

This commit is contained in:
Martin Mathieson 2023-09-15 14:17:51 +00:00
parent d11826a051
commit 6d5496f192
15 changed files with 6572 additions and 1582 deletions

View File

@ -121,6 +121,7 @@ set(CLEAN_ASN1_DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-isdn-sup.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-its.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-kerberos.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-kpm-v2.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-lcsap.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-ldap.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-lnpdqp.c

View File

@ -63,6 +63,7 @@ set(ASN1_SRC_DIRS
isdn-sup
its
kerberos
kpm-v2
lcsap
ldap
lnpdqp

View File

@ -12,7 +12,7 @@ set( PROTOCOL_NAME e2ap )
set( PROTO_OPT )
set( EXPORT_FILES
${PROTOCOL_NAME}-exp.cnf
${PROTOCOL_NAME}-exp.cnf
)
set( EXT_ASN_FILE_LIST
@ -26,7 +26,7 @@ set( ASN_FILE_LIST
E2AP-PDU-Contents.asn
E2AP-PDU-Descriptions.asn
e2sm-v3.01.asn
e2sm-rc-v3.00.asn
e2sm-rc-v1.03.asn
e2sm-kpm-v3.00.asn
e2sm-ni-v1.00.asn
)

View File

@ -23,7 +23,6 @@ E2SM-KPM-ActionDefinition
E2SM-KPM-IndicationHeader
E2SM-KPM-IndicationMessage
E2SM-KPM-RANfunction-Description
#E2SM-KPM-CallProcessID (no such function)
E2SM-RC-EventTrigger
E2SM-RC-ActionDefinition
@ -35,9 +34,9 @@ E2SM-RC-ControlHeader
E2SM-RC-ControlMessage
E2SM-RC-ControlOutcome
# New for v3
E2SM-RC-QueryOutcome
E2SM-RC-QueryDefinition
E2SM-RC-QueryHeader
# E2SM-RC-QueryOutcome
# E2SM-RC-QueryDefinition
# E2SM-RC-QueryHeader
E2SM-NI-EventTriggerDefinition
@ -246,18 +245,29 @@ SuccessfulOutcome/value successfulOutcome_value
#.FN_BODY RANfunctionDefinition VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
/* We know that the next thing is a RANFunction-Name, but it's wrapped up in a sequence,
so can't silently/hiddenly call ranFunctionName here... */
%(DEFAULT_BODY)s
/* Looking for shortName string near beginning of tvb */
gboolean found = FALSE;
for (int n=KPM_RANFUNCTIONS; n<MAX_RANFUNCTIONS; n++) {
/* For each RAN function name.. */
for (int n=KPM_RANFUNCTIONS; n<MAX_RANFUNCTIONS && !found; n++) {
guint32 tvb_len = tvb_captured_length(parameter_tvb);
guint name_len = (gint)strlen(g_ran_functioname_table[n].name);
guint name_len = (gint)strlen(g_ran_function_name_table[n]);
/* For each of several byte positions.. */
for (int m=0; (m<30) && ((m+name_len+1))<tvb_len; m++) {
if (tvb_strneql(parameter_tvb, m, g_ran_functioname_table[n].name, name_len) == 0) {
/* Call the set's dissector */
g_ran_functioname_table[n].functions.ran_function_definition_dissector(parameter_tvb, actx->pinfo, tree, NULL);
found = TRUE;
break;
/* Have we found a match on the name? */
if (tvb_strneql(parameter_tvb, m, g_ran_function_name_table[n], name_len) == 0) {
/* TODO: we don't yet know the OID (hopefully won't make a difference for this message though...),
so for now just call with the first/only available dissector for this RAN Function name */
if (g_ran_functions_available_dissectors[n].num_available_dissectors) {
g_ran_functions_available_dissectors[n].ran_function_dissectors[0]->functions.ran_function_definition_dissector(parameter_tvb, actx->pinfo, tree, NULL);
found = TRUE;
break;
}
}
}
}
@ -267,53 +277,82 @@ SuccessfulOutcome/value successfulOutcome_value
"ShortName does not match any known Service Model");
}
#.FN_BODY RANfunction-Name/ranFunction-ShortName VAL_PTR=&value_tvb
tvbuff_t *value_tvb;
%(DEFAULT_BODY)s
if (!actx->pinfo->fd->visited) {
/* N.B. too early to work out exact dissector, as don't have OID yet */
e2ap_store_ran_function_mapping(actx->pinfo,
tvb_get_string_enc(wmem_packet_scope(), value_tvb, 0, tvb_captured_length(value_tvb), ENC_ASCII));
}
#.FN_BODY RANfunction-Name/ranFunction-E2SM-OID VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
e2ap_update_ran_function_mapping(actx->pinfo, tree, parameter_tvb,
tvb_get_string_enc(actx->pinfo->pool, parameter_tvb, 0,
tvb_captured_length(parameter_tvb), ENC_ASCII));
#.FN_BODY RICcontrolHeader VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ric_control_header_dissector) {
functions->ric_control_header_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ric_control_header_dissector) {
dissector->functions.ric_control_header_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICcontrolMessage VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ric_control_message_dissector) {
functions->ric_control_message_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ric_control_message_dissector) {
dissector->functions.ric_control_message_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICcontrolOutcome VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ric_control_outcome_dissector) {
functions->ric_control_outcome_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ric_control_outcome_dissector) {
dissector->functions.ric_control_outcome_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICqueryOutcome VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ric_query_outcome_dissector) {
functions->ric_query_outcome_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ric_query_outcome_dissector) {
dissector->functions.ric_query_outcome_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICqueryDefinition VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ric_query_definition_dissector) {
functions->ric_query_definition_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ric_query_definition_dissector) {
dissector->functions.ric_query_definition_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICqueryHeader VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ric_query_header_dissector) {
functions->ric_query_header_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ric_query_header_dissector) {
dissector->functions.ric_query_header_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
@ -321,41 +360,51 @@ SuccessfulOutcome/value successfulOutcome_value
#.FN_BODY RICeventTriggerDefinition VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ran_event_trigger_dissector) {
functions->ran_event_trigger_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ran_event_trigger_dissector) {
dissector->functions.ran_event_trigger_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICactionDefinition VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ran_action_definition_dissector) {
functions->ran_action_definition_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ran_action_definition_dissector) {
dissector->functions.ran_action_definition_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICindicationHeader VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ran_indication_header_dissector) {
functions->ran_indication_header_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ran_indication_header_dissector) {
dissector->functions.ran_indication_header_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICindicationMessage VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ran_indication_message_dissector) {
functions->ran_indication_message_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ran_indication_message_dissector) {
dissector->functions.ran_indication_message_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
#.FN_BODY RICcallProcessID VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
ran_function_pointers_t* functions = lookup_ranfunction_pointers(actx->pinfo, tree, parameter_tvb);
if (functions && functions->ran_callprocessid_dissector) {
functions->ran_callprocessid_dissector(parameter_tvb, actx->pinfo, tree, NULL);
ran_function_dissector_t* dissector = lookup_ranfunction_dissector(actx->pinfo, tree, parameter_tvb);
if (dissector) {
if (dissector->functions.ran_callprocessid_dissector) {
dissector->functions.ran_callprocessid_dissector(parameter_tvb, actx->pinfo, tree, NULL);
}
}
# ################################################################################
@ -663,14 +712,6 @@ RICQueryResponse N e2ap.proc.sout id-RICquery
e2ap_data->ran_function_id = value;
#.FN_BODY RANfunction-Name/ranFunction-ShortName VAL_PTR=&value_tvb
tvbuff_t *value_tvb;
%(DEFAULT_BODY)s
struct e2ap_private_data *e2ap_data = e2ap_get_private_data(actx->pinfo);
ran_functionid_table_t *table = get_ran_functionid_table(actx->pinfo);
store_ran_function_mapping(actx->pinfo, table, e2ap_data,
tvb_get_string_enc(wmem_packet_scope(), value_tvb, 0, tvb_captured_length(value_tvb), ENC_ASCII));
#.FN_BODY GlobalgNB-ID/gnb-id
int start_offset = offset;
%(DEFAULT_BODY)s

File diff suppressed because it is too large Load Diff

View File

@ -8,11 +8,10 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* References: ORAN-WG3.E2AP-v02.01, ORAN-WG3.E2SM-KPM-v02.02, ORAN-WG3.E2SM-RC.01.02
* References: ORAN-WG3.E2AP-v03.00, ORAN-WG3.E2SM-KPM-v03.00, ORAN-WG3.E2SM-RC.03.00
*/
#include "config.h"
#include <stdio.h>
#include <epan/packet.h>
#include <epan/strutil.h>
@ -22,9 +21,8 @@
#include <epan/expert.h>
#include <epan/proto_data.h>
#include <epan/conversation.h>
#include <epan/exceptions.h>
#include <epan/show_exception.h>
#include <epan/to_str.h>
#include <epan/oids.h>
#include "packet-e2ap.h"
#include "packet-per.h"
@ -50,18 +48,23 @@ static int hf_e2ap_unmapped_ran_function_id = -1;
static int hf_e2ap_ran_function_name_not_recognised = -1;
static int hf_e2ap_ran_function_setup_frame = -1;
static int hf_e2ap_dissector_version= -1;
static int hf_e2ap_frame_version = -1;
/* Initialize the subtree pointers */
static gint ett_e2ap = -1;
static expert_field ei_e2ap_ran_function_names_no_match = EI_INIT;
static expert_field ei_e2ap_ran_function_id_not_mapped = EI_INIT;
static expert_field ei_e2ap_ran_function_dissector_mismatch = EI_INIT;
#include "packet-e2ap-ett.c"
/* Forward declarations */
static int dissect_e2ap_RANfunction_Name(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
static int dissect_E2SM_KPM_EventTriggerDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_KPM_ActionDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_KPM_IndicationHeader_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
@ -77,9 +80,9 @@ static int dissect_E2SM_RC_CallProcessID_PDU(tvbuff_t *tvb _U_, packet_info *pin
static int dissect_E2SM_RC_ControlHeader_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_RC_ControlMessage_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_RC_ControlOutcome_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_RC_QueryOutcome_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_RC_QueryDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_RC_QueryHeader_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
//static int dissect_E2SM_RC_QueryOutcome_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
//static int dissect_E2SM_RC_QueryDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
//static int dissect_E2SM_RC_QueryHeader_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_NI_EventTriggerDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_NI_ActionDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
@ -91,8 +94,6 @@ static int dissect_E2SM_NI_ControlHeader_PDU(tvbuff_t *tvb _U_, packet_info *pin
static int dissect_E2SM_NI_ControlMessage_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_NI_ControlOutcome_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
enum {
INITIATING_MESSAGE,
SUCCESSFUL_OUTCOME,
@ -107,7 +108,7 @@ typedef struct _e2ap_ctx_t {
} e2ap_ctx_t;
/* Temporary private info to remember while dissecting frame */
struct e2ap_private_data {
guint32 procedure_code;
guint32 protocol_ie_id;
@ -122,6 +123,7 @@ struct e2ap_private_data {
dissector_handle_t component_configuration_dissector;
};
/* Lookup temporary private info */
static struct e2ap_private_data*
e2ap_get_private_data(packet_info *pinfo)
{
@ -138,102 +140,24 @@ e2ap_get_private_data(packet_info *pinfo)
/* TODO: unfortunately, it seems that different versions of these protocols are not backward-compatible, so */
/* it would be good to show where (going by OID) the dissector isn't at the same version as the message.. */
/* An alternative would be to have multiple versions of each protocol and have them register in tables... */
typedef int (*pdu_dissector_t)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
/* Function pointers for a RANFunction */
typedef struct {
pdu_dissector_t ran_function_definition_dissector;
pdu_dissector_t ric_control_header_dissector;
pdu_dissector_t ric_control_message_dissector;
pdu_dissector_t ric_control_outcome_dissector;
/* new for v3 */
pdu_dissector_t ric_query_outcome_dissector;
pdu_dissector_t ric_query_definition_dissector;
pdu_dissector_t ric_query_header_dissector;
pdu_dissector_t ran_action_definition_dissector;
pdu_dissector_t ran_indication_message_dissector;
pdu_dissector_t ran_indication_header_dissector;
pdu_dissector_t ran_callprocessid_dissector;
pdu_dissector_t ran_event_trigger_dissector;
} ran_function_pointers_t;
typedef enum {
MIN_RANFUNCTIONS,
KPM_RANFUNCTIONS=0,
RIC_RANFUNCTIONS,
NI_RANFUNCTIONS,
MAX_RANFUNCTIONS
} ran_function_t;
typedef struct {
const char* name;
ran_function_pointers_t functions;
} ran_function_name_mapping_t;
/* Static table mapping from string -> ran_function */
static const ran_function_name_mapping_t g_ran_functioname_table[MAX_RANFUNCTIONS] =
static const char* g_ran_function_name_table[MAX_RANFUNCTIONS] =
{
{ "ORAN-E2SM-KPM", { dissect_E2SM_KPM_RANfunction_Description_PDU,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
dissect_E2SM_KPM_ActionDefinition_PDU,
dissect_E2SM_KPM_IndicationMessage_PDU,
dissect_E2SM_KPM_IndicationHeader_PDU,
NULL, /* no dissect_E2SM_KPM_CallProcessID_PDU */
dissect_E2SM_KPM_EventTriggerDefinition_PDU
}
},
{ "ORAN-E2SM-RC", { dissect_E2SM_RC_RANFunctionDefinition_PDU,
dissect_E2SM_RC_ControlHeader_PDU,
dissect_E2SM_RC_ControlMessage_PDU,
dissect_E2SM_RC_ControlOutcome_PDU,
/* new for v3 */
dissect_E2SM_RC_QueryOutcome_PDU,
dissect_E2SM_RC_QueryDefinition_PDU,
dissect_E2SM_RC_QueryHeader_PDU,
dissect_E2SM_RC_ActionDefinition_PDU,
dissect_E2SM_RC_IndicationMessage_PDU,
dissect_E2SM_RC_IndicationHeader_PDU,
dissect_E2SM_RC_CallProcessID_PDU,
dissect_E2SM_RC_EventTrigger_PDU
}
},
{ "ORAN-E2SM-NI", { dissect_E2SM_NI_RANfunction_Description_PDU,
dissect_E2SM_NI_ControlHeader_PDU,
dissect_E2SM_NI_ControlMessage_PDU,
dissect_E2SM_NI_ControlOutcome_PDU,
NULL,
NULL,
NULL,
dissect_E2SM_NI_ActionDefinition_PDU,
dissect_E2SM_NI_IndicationMessage_PDU,
dissect_E2SM_NI_IndicationHeader_PDU,
dissect_E2SM_NI_CallProcessID_PDU,
dissect_E2SM_NI_EventTriggerDefinition_PDU
}
}
"ORAN-E2SM-KPM",
"ORAN-E2SM-RC",
"ORAN-E2SM-NI"
};
/* Per-conversation mapping: ranFunctionId -> ran_function */
/* Per-conversation mapping: ranFunctionId -> ran_function+dissector */
typedef struct {
guint32 setup_frame;
guint32 ran_function_id;
ran_function_t ran_function;
ran_function_pointers_t *ran_function_pointers;
char oid[MAX_OID_LEN]; // i.e., OID from setupRequest
ran_function_dissector_t *dissector;
} ran_function_id_mapping_t;
typedef struct {
@ -247,27 +171,49 @@ static const char *ran_function_to_str(ran_function_t ran_function)
switch (ran_function) {
case KPM_RANFUNCTIONS:
return "KPM";
case RIC_RANFUNCTIONS:
return "RIC";
case RC_RANFUNCTIONS:
return "RC";
case NI_RANFUNCTIONS:
return "NI";
default:
return "Unknown";
}
}
/* Table of RAN Function tables, indexed by gnbId (bytes) */
typedef struct {
#define MAX_GNBS 6
guint32 num_gnbs;
struct {
guint32 len;
guint8 value[MAX_GNB_ID_BYTES];
guint8 id_value[MAX_GNB_ID_BYTES];
guint32 id_len;
ran_functionid_table_t *ran_function_table;
} gnb[MAX_GNBS];
} gnb_ran_functions_t;
static gnb_ran_functions_t s_gnb_ran_functions;
static gnb_ran_functions_t s_gnb_ran_functions_table;
/* Table of available dissectors for each RAN function */
typedef struct {
guint32 num_available_dissectors;
#define MAX_DISSECTORS_PER_RAN_FUNCTION 3
ran_function_dissector_t* ran_function_dissectors[MAX_DISSECTORS_PER_RAN_FUNCTION];
} ran_function_available_dissectors_t;
/* Available dissectors should be set here */
static ran_function_available_dissectors_t g_ran_functions_available_dissectors[MAX_RANFUNCTIONS];
/* TODO: will be called from outside this file by separate dissectors */
void register_e2ap_ran_function_dissector(ran_function_t ran_function, ran_function_dissector_t *dissector)
{
if ((ran_function >= MIN_RANFUNCTIONS) && (ran_function <= MAX_RANFUNCTIONS)) {
ran_function_available_dissectors_t *available_dissectors = &g_ran_functions_available_dissectors[ran_function];
if (available_dissectors->num_available_dissectors < MAX_DISSECTORS_PER_RAN_FUNCTION) {
available_dissectors->ran_function_dissectors[available_dissectors->num_available_dissectors++] = dissector;
}
}
}
/* Get RANfunctionID table from conversation data - create new if necessary */
@ -298,8 +244,11 @@ static ran_functionid_table_t* get_ran_functionid_table(packet_info *pinfo)
/* Store new RANfunctionID -> Service Model mapping in table */
static void store_ran_function_mapping(packet_info *pinfo, ran_functionid_table_t *table, struct e2ap_private_data *e2ap_data, const char *name)
void e2ap_store_ran_function_mapping(packet_info *pinfo, const char *name)
{
struct e2ap_private_data *e2ap_data = e2ap_get_private_data(pinfo);
ran_functionid_table_t *table = get_ran_functionid_table(pinfo);
if (!name) {
return;
}
@ -312,13 +261,18 @@ static void store_ran_function_mapping(packet_info *pinfo, ran_functionid_table_
guint32 ran_function_id = e2ap_data->ran_function_id;
ran_function_t ran_function = MAX_RANFUNCTIONS; /* i.e. invalid */
ran_function_pointers_t *ran_function_pointers = NULL;
ran_function_dissector_t *ran_function_dissector = NULL;
/* Check known RAN functions */
/* Check known RAN function names */
for (int n=MIN_RANFUNCTIONS; n < MAX_RANFUNCTIONS; n++) {
if (strcmp(name, g_ran_functioname_table[n].name) == 0) {
if (strcmp(name, g_ran_function_name_table[n]) == 0) {
ran_function = n;
ran_function_pointers = (ran_function_pointers_t*)&(g_ran_functioname_table[n].functions);
/* Don't know OID yet, so for now, just choose first/only one */
/* TODO: is latest one likely to be more compatible? First fields (at least) come from E2SM.. */
if (g_ran_functions_available_dissectors[table->entries[n].ran_function].num_available_dissectors) {
ran_function_dissector = g_ran_functions_available_dissectors[table->entries[n].ran_function].ran_function_dissectors[0];
}
break;
}
}
@ -328,7 +282,7 @@ static void store_ran_function_mapping(packet_info *pinfo, ran_functionid_table_
return;
}
/* If ID already mapped, ignore */
/* If ID already mapped, can stop here */
for (guint n=0; n < table->num_entries; n++) {
if (table->entries[n].ran_function_id == ran_function_id) {
return;
@ -340,7 +294,7 @@ static void store_ran_function_mapping(packet_info *pinfo, ran_functionid_table_
table->entries[idx].setup_frame = pinfo->num;
table->entries[idx].ran_function_id = ran_function_id;
table->entries[idx].ran_function = ran_function;
table->entries[idx].ran_function_pointers = ran_function_pointers;
table->entries[idx].dissector = ran_function_dissector;
/* When add first entry, also want to set up table from gnbId -> table */
if (idx == 0) {
@ -348,10 +302,10 @@ static void store_ran_function_mapping(packet_info *pinfo, ran_functionid_table_
guint8 *id_value = &e2ap_data->gnb_id_bytes[0];
gboolean found = FALSE;
for (guint n=0; n<s_gnb_ran_functions.num_gnbs; n++) {
if ((s_gnb_ran_functions.gnb[n].len = id_len) &&
(memcmp(s_gnb_ran_functions.gnb[n].value, id_value, id_len) == 0)) {
// Already have an entry for this gnb.
for (guint n=0; n<s_gnb_ran_functions_table.num_gnbs; n++) {
if ((s_gnb_ran_functions_table.gnb[n].id_len = id_len) &&
(memcmp(s_gnb_ran_functions_table.gnb[n].id_value, id_value, id_len) == 0)) {
/* Already have an entry for this gnb. */
found = TRUE;
break;
}
@ -359,51 +313,174 @@ static void store_ran_function_mapping(packet_info *pinfo, ran_functionid_table_
if (!found) {
/* Add entry (if room for 1 more) */
guint32 new_idx = s_gnb_ran_functions.num_gnbs;
guint32 new_idx = s_gnb_ran_functions_table.num_gnbs;
if (new_idx < MAX_GNBS-1) {
s_gnb_ran_functions.gnb[new_idx].len = id_len;
memcpy(s_gnb_ran_functions.gnb[new_idx].value, id_value, id_len);
s_gnb_ran_functions.gnb[new_idx].ran_function_table = table;
s_gnb_ran_functions_table.gnb[new_idx].id_len = id_len;
memcpy(s_gnb_ran_functions_table.gnb[new_idx].id_value, id_value, id_len);
s_gnb_ran_functions_table.gnb[new_idx].ran_function_table = table;
s_gnb_ran_functions.num_gnbs++;
s_gnb_ran_functions_table.num_gnbs++;
}
}
}
}
/* Look for Service Model function pointers, based on current RANFunctionID in pinfo */
static ran_function_pointers_t* lookup_ranfunction_pointers(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
static ran_function_dissector_t* lookup_ranfunction_dissector(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
{
/* Get ranFunctionID from this frame */
struct e2ap_private_data *e2ap_data = e2ap_get_private_data(pinfo);
guint ran_function_id = e2ap_data->ran_function_id;
/* Look in table function pointers for this ranFunctionID */
/* Get ranFunction table corresponding to this frame's conversation */
ran_functionid_table_t *table = get_ran_functionid_table(pinfo);
if (!table) {
/* There is no ran function table associated with this frame's conversation info */
return NULL;
}
/* Find the entry in this table corresponding to ran_function_id */
for (guint n=0; n < table->num_entries; n++) {
if (ran_function_id == table->entries[n].ran_function_id) {
/* Point back at the setup frame where this ranfunction was mapped */
proto_item *ti = proto_tree_add_uint(tree, hf_e2ap_ran_function_setup_frame,
tvb, 0, 0, table->entries[n].setup_frame);
/* Also show that mapping */
proto_item_append_text(ti, " (%u -> %s)", table->entries[n].ran_function_id, ran_function_to_str(table->entries[n].ran_function));
proto_item_set_generated(ti);
if (tree) {
/* Point back at the setup frame where this ranfunction was mapped */
proto_item *ti = proto_tree_add_uint(tree, hf_e2ap_ran_function_setup_frame,
tvb, 0, 0, table->entries[n].setup_frame);
/* Show that mapping */
proto_item_append_text(ti, " (%u -> %s)", table->entries[n].ran_function_id, ran_function_to_str(table->entries[n].ran_function));
proto_item_set_generated(ti);
return table->entries[n].ran_function_pointers;
/* Also take the chance to compare signalled and available dissector */
char *frame_version = oid_resolved_from_string(pinfo->pool, table->entries[n].oid);
ti = proto_tree_add_string(tree, hf_e2ap_frame_version, tvb, 0, 0, frame_version);
proto_item_set_generated(ti);
char *dissector_version = oid_resolved_from_string(pinfo->pool, table->entries[n].dissector->oid);
ti = proto_tree_add_string(tree, hf_e2ap_dissector_version, tvb, 0, 0, dissector_version);
proto_item_set_generated(ti);
if (strcmp(frame_version, dissector_version) != 0) {
/* Expert info for version mismatch! */
expert_add_info_format(pinfo, ti, &ei_e2ap_ran_function_dissector_mismatch,
"Dissector version mismatch - frame is %s but dissector is %s",
frame_version, dissector_version);
}
}
/* Return the dissector */
return table->entries[n].dissector;
}
}
/* No match found.. */
proto_item *ti = proto_tree_add_item(tree, hf_e2ap_unmapped_ran_function_id, tvb, 0, 0, ENC_NA);
expert_add_info_format(pinfo, ti, &ei_e2ap_ran_function_id_not_mapped,
"Service Model not mapped for FunctionID %u", ran_function_id);
if (tree) {
/* No match found.. */
proto_item *ti = proto_tree_add_item(tree, hf_e2ap_unmapped_ran_function_id, tvb, 0, 0, ENC_NA);
expert_add_info_format(pinfo, ti, &ei_e2ap_ran_function_id_not_mapped,
"Service Model not mapped for FunctionID %u", ran_function_id);
}
return NULL;
}
static char* lookup_ranfunction_oid(packet_info *pinfo)
{
/* Get ranFunctionID from this frame */
struct e2ap_private_data *e2ap_data = e2ap_get_private_data(pinfo);
guint ran_function_id = e2ap_data->ran_function_id;
/* Get ranFunction table corresponding to this frame's conversation */
ran_functionid_table_t *table = get_ran_functionid_table(pinfo);
if (!table) {
/* There is no ran function table associated with this frame's conversation info */
return NULL;
}
/* Find the entry in this table corresponding to ran_function_id */
for (guint n=0; n < table->num_entries; n++) {
if (ran_function_id == table->entries[n].ran_function_id) {
return (char*)(table->entries[n].oid);
}
}
/* Not found */
return "";
}
/* We now know the OID - can we set a dissector that is an exact match from what has been signalled? */
static void update_dissector_using_oid(packet_info *pinfo, ran_function_t ran_function)
{
char *frame_oid = lookup_ranfunction_oid(pinfo);
gboolean found = FALSE;
/* Look at available dissectors for this RAN function */
ran_function_available_dissectors_t *available = &g_ran_functions_available_dissectors[ran_function];
if (!available->num_available_dissectors) {
/* Oops - none available at all! */
return;
}
// Get mapping in use
struct e2ap_private_data *e2ap_data = e2ap_get_private_data(pinfo);
guint ran_function_id = e2ap_data->ran_function_id;
ran_function_id_mapping_t *mapping = NULL;
ran_functionid_table_t *table = get_ran_functionid_table(pinfo);
/* Find the entry in this table corresponding to ran_function_id */
for (guint n=0; n < table->num_entries; n++) {
if (ran_function_id == table->entries[n].ran_function_id) {
mapping = &(table->entries[n]);
}
}
if (!mapping) {
return;
}
/* Set dissector pointer in ran_function_id_mapping_t */
for (guint32 n=0; n < available->num_available_dissectors; n++) {
/* If exact match, set it */
if (strcmp(frame_oid, available->ran_function_dissectors[n]->oid) == 0) {
mapping->dissector = available->ran_function_dissectors[n];
found = TRUE;
break;
}
}
/* If not exact match, just set to first one available (TODO: closest above better?) */
if (!found) {
mapping->dissector = available->ran_function_dissectors[0];
}
}
/* Update RANfunctionID -> Service Model mapping in table (now that we know OID) */
void e2ap_update_ran_function_mapping(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, const char *oid)
{
/* Copy OID into table entry (so may be used to choose and be compared with chosen available dissector */
struct e2ap_private_data *e2ap_data = e2ap_get_private_data(pinfo);
ran_functionid_table_t *table = get_ran_functionid_table(pinfo);
ran_function_t ran_function = MAX_RANFUNCTIONS;
for (guint n=0; n < table->num_entries; n++) {
if (e2ap_data->ran_function_id == table->entries[n].ran_function_id) {
ran_function = table->entries[n].ran_function;
g_strlcpy(table->entries[n].oid, oid, MAX_OID_LEN);
}
}
/* Look up version from oid and show as generated field */
char *version = oid_resolved_from_string(pinfo->pool, oid);
proto_item *ti = proto_tree_add_string(tree, hf_e2ap_frame_version, tvb, 0, 0, version);
proto_item_set_generated(ti);
// Can now pick most appropriate dissector for this RAN Function name, based upon this OID and the available dissectors.
if (ran_function < MAX_RANFUNCTIONS) {
if (pinfo->fd->visited) {
update_dissector_using_oid(pinfo, ran_function);
}
}
}
/* This will get used for E2nodeConfigurationUpdate, where we have a gnb-id but haven't seen E2setupRequest */
static void update_conversation_from_gnb_id(asn1_ctx_t *actx)
{
@ -431,13 +508,13 @@ static void update_conversation_from_gnb_id(asn1_ctx_t *actx)
guint id_len = e2ap_data->gnb_id_len;
guint8 *id_value = &e2ap_data->gnb_id_bytes[0];
for (guint n=0; n<s_gnb_ran_functions.num_gnbs; n++) {
if ((s_gnb_ran_functions.gnb[n].len = id_len) &&
(memcmp(s_gnb_ran_functions.gnb[n].value, id_value, id_len) == 0)) {
for (guint n=0; n<s_gnb_ran_functions_table.num_gnbs; n++) {
if ((s_gnb_ran_functions_table.gnb[n].id_len = id_len) &&
(memcmp(s_gnb_ran_functions_table.gnb[n].id_value, id_value, id_len) == 0)) {
/* Have an entry for this gnb. Set direct pointer to existing data (used by original conversation). */
/* N.B. This means that no further updates for the gNB are expected on different conversations.. */
p_conv_data = s_gnb_ran_functions.gnb[n].ran_function_table;
p_conv_data = s_gnb_ran_functions_table.gnb[n].ran_function_table;
conversation_add_proto_data(p_conv, proto_e2ap, p_conv_data);
/* TODO: may want to try to add a generated field to pass back to E2setupRequest where RAN function mappings were first seen? */
@ -548,7 +625,7 @@ dissect_e2ap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
static void e2ap_init_protocol(void)
{
s_gnb_ran_functions.num_gnbs = 0;
s_gnb_ran_functions_table.num_gnbs = 0;
}
@ -562,6 +639,90 @@ proto_reg_handoff_e2ap(void)
dissector_add_uint("sctp.ppi", E2_DU_PROTOCOL_ID, e2ap_handle);
#include "packet-e2ap-dis-tab.c"
/********************************/
/* Known OIDs for RAN providers */
/* KPM */
oid_add_from_string("KPM v1", "1.3.6.1.4.1.53148.1.1.2.2");
oid_add_from_string("KPM v2", "1.3.6.1.4.1.53148.1.2.2.2");
oid_add_from_string("KPM v3", "1.2.6.1.4.1.53148.1.3.2.2");
/* RC */
// TODO: appears to be the same??? Asking for clarification from ORAN..
oid_add_from_string("RC v1", "1.3.6.1.4.1.53148.1.1.2.3");
//oid_add_from_string("RC v3", "1.3.6.1.4.1.53148.1.1.2.3");
//oid_add_from_string("RC v4", "1.3.6.1.4.1.53148.1.1.2.3");
/* NI */
oid_add_from_string("NI v1", "1.3.6.1.4.1.53148.1.1.2.1");
/********************************/
/* Register 'built-in' dissectors */
static ran_function_dissector_t kpm_v3 =
{ "ORAN-E2SM-KPM", "1.2.6.1.4.1.53148.1.3.2.2", 3, 0,
{ dissect_E2SM_KPM_RANfunction_Description_PDU,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
dissect_E2SM_KPM_ActionDefinition_PDU,
dissect_E2SM_KPM_IndicationMessage_PDU,
dissect_E2SM_KPM_IndicationHeader_PDU,
NULL, /* no dissect_E2SM_KPM_CallProcessID_PDU */
dissect_E2SM_KPM_EventTriggerDefinition_PDU
}
};
static ran_function_dissector_t rc_v1 =
{ "ORAN-E2SM-RC", "1.3.6.1.4.1.53148.1.1.2.3", 1, 3,
{ dissect_E2SM_RC_RANFunctionDefinition_PDU,
dissect_E2SM_RC_ControlHeader_PDU,
dissect_E2SM_RC_ControlMessage_PDU,
dissect_E2SM_RC_ControlOutcome_PDU,
/* new for v3 */
NULL, //dissect_E2SM_RC_QueryOutcome_PDU,
NULL, //dissect_E2SM_RC_QueryDefinition_PDU,
NULL, //dissect_E2SM_RC_QueryHeader_PDU,
dissect_E2SM_RC_ActionDefinition_PDU,
dissect_E2SM_RC_IndicationMessage_PDU,
dissect_E2SM_RC_IndicationHeader_PDU,
dissect_E2SM_RC_CallProcessID_PDU,
dissect_E2SM_RC_EventTrigger_PDU
}
};
static ran_function_dissector_t ni_v1 =
{ "ORAN-E2SM-NI", "1.3.6.1.4.1.53148.1.1.2.1", 1, 0,
{ dissect_E2SM_NI_RANfunction_Description_PDU,
dissect_E2SM_NI_ControlHeader_PDU,
dissect_E2SM_NI_ControlMessage_PDU,
dissect_E2SM_NI_ControlOutcome_PDU,
NULL,
NULL,
NULL,
dissect_E2SM_NI_ActionDefinition_PDU,
dissect_E2SM_NI_IndicationMessage_PDU,
dissect_E2SM_NI_IndicationHeader_PDU,
dissect_E2SM_NI_CallProcessID_PDU,
dissect_E2SM_NI_EventTriggerDefinition_PDU
}
};
/* Register available dissectors. TODO: break these out into separate
* ASN.1 protocols that register themselves */
register_e2ap_ran_function_dissector(KPM_RANFUNCTIONS, &kpm_v3);
register_e2ap_ran_function_dissector(RC_RANFUNCTIONS, &rc_v1);
register_e2ap_ran_function_dissector(NI_RANFUNCTIONS, &ni_v1);
}
@ -584,7 +745,16 @@ void proto_register_e2ap(void) {
{ &hf_e2ap_ran_function_setup_frame,
{ "RANfunction setup frame", "e2ap.setup-frame",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
NULL, HFILL }}
NULL, HFILL }},
{ &hf_e2ap_dissector_version,
{ "Version (dissector)", "e2ap.version.dissector",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
{ &hf_e2ap_frame_version,
{ "Version (frame)", "e2ap.version.frame",
FT_STRING, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
};
/* List of subtrees */
@ -596,6 +766,8 @@ void proto_register_e2ap(void) {
static ei_register_info ei[] = {
{ &ei_e2ap_ran_function_names_no_match, { "e2ap.ran-function-names-no-match", PI_PROTOCOL, PI_WARN, "RAN Function name doesn't match known service models", EXPFILL }},
{ &ei_e2ap_ran_function_id_not_mapped, { "e2ap.ran-function-id-not-known", PI_PROTOCOL, PI_WARN, "Service Model not known for RANFunctionID", EXPFILL }},
{ &ei_e2ap_ran_function_dissector_mismatch, { "e2ap.ran-function-dissector-version-mismatch", PI_PROTOCOL, PI_WARN, "Available dissector does not match signalled", EXPFILL }},
};
expert_module_t* expert_e2ap;

View File

@ -0,0 +1,39 @@
# CMakeLists.txt
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 1998 Gerald Combs
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
set( PROTOCOL_NAME kpm-v2 )
set( PROTO_OPT )
set( EXPORT_FILES
${PROTOCOL_NAME}-exp.cnf
)
set( EXT_ASN_FILE_LIST
)
set( ASN_FILE_LIST
e2sm-kpm-v2.02.asn
e2sm-v3.01.asn
)
set( EXTRA_DIST
${ASN_FILE_LIST}
packet-${PROTOCOL_NAME}-template.c
${PROTOCOL_NAME}.cnf
)
set( SRC_FILES
${EXTRA_DIST}
${EXT_ASN_FILE_LIST}
)
set( A2W_FLAGS )
ASN2WRS()

View File

@ -0,0 +1,384 @@
-- ASN1START
-- **************************************************************
-- E2SM-KPM Information Element Definitions
-- **************************************************************
E2SM-KPM-IEs {
iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) oran(53148) e2(1) version2(2) e2sm(2) e2sm-KPMMON-IEs (2)}
DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
-- **************************************************************
-- IEs
-- **************************************************************
IMPORTS
CGI,
FiveQI,
PLMNIdentity,
QCI,
QosFlowIdentifier,
RANfunction-Name,
RIC-Format-Type,
RIC-Style-Name,
RIC-Style-Type,
S-NSSAI,
UEID
FROM E2SM-COMMON-IEs;
TimeStamp ::= OCTET STRING (SIZE(4))
GranularityPeriod ::= INTEGER (1.. 4294967295)
MeasurementType ::= CHOICE {
measName MeasurementTypeName,
measID MeasurementTypeID,
...
}
MeasurementTypeName ::= PrintableString(SIZE(1.. 150, ...))
MeasurementTypeID ::= INTEGER (1.. 65536, ...)
MeasurementLabel ::= SEQUENCE {
noLabel ENUMERATED {true, ...} OPTIONAL,
-- TODO: changed from PLMNIdentity and S-NSSAI
plmnID PLMNIdentity OPTIONAL,
sliceID S-NSSAI OPTIONAL,
fiveQI FiveQI OPTIONAL,
qFI QosFlowIdentifier OPTIONAL,
qCI QCI OPTIONAL,
qCImax QCI OPTIONAL,
qCImin QCI OPTIONAL,
aRPmax INTEGER (1.. 15, ...) OPTIONAL,
aRPmin INTEGER (1.. 15, ...) OPTIONAL,
bitrateRange INTEGER (1.. 65535, ...) OPTIONAL,
layerMU-MIMO INTEGER (1.. 65535, ...) OPTIONAL,
sUM ENUMERATED {true, ...} OPTIONAL,
distBinX INTEGER (1.. 65535, ...) OPTIONAL,
distBinY INTEGER (1.. 65535, ...) OPTIONAL,
distBinZ INTEGER (1.. 65535, ...) OPTIONAL,
preLabelOverride ENUMERATED {true, ...} OPTIONAL,
startEndInd ENUMERATED {start, end, ...} OPTIONAL,
min ENUMERATED {true, ...} OPTIONAL,
max ENUMERATED {true, ...} OPTIONAL,
avg ENUMERATED {true, ...} OPTIONAL,
...
}
TestCondInfo ::= SEQUENCE{
testType TestCond-Type,
testExpr TestCond-Expression OPTIONAL,
testValue TestCond-Value OPTIONAL,
...
}
TestCond-Type ::= CHOICE{
gBR ENUMERATED {true, ...},
aMBR ENUMERATED {true, ...},
isStat ENUMERATED {true, ...},
isCatM ENUMERATED {true, ...},
rSRP ENUMERATED {true, ...},
rSRQ ENUMERATED {true, ...},
...,
ul-rSRP ENUMERATED {true, ...},
cQI ENUMERATED {true, ...},
fiveQI ENUMERATED {true, ...},
qCI ENUMERATED {true, ...},
sNSSAI ENUMERATED {true, ...}
}
TestCond-Expression ::= ENUMERATED {
equal,
greaterthan,
lessthan,
contains,
present,
...
}
TestCond-Value ::= CHOICE{
valueInt INTEGER,
valueEnum INTEGER,
valueBool BOOLEAN,
valueBitS BIT STRING,
valueOctS OCTET STRING,
valuePrtS PrintableString,
...,
valueReal REAL
}
-- **************************************************************
-- Lists
-- **************************************************************
maxnoofCells INTEGER ::= 16384
maxnoofRICStyles INTEGER ::= 63
maxnoofMeasurementInfo INTEGER ::= 65535
maxnoofLabelInfo INTEGER ::= 2147483647
maxnoofMeasurementRecord INTEGER ::= 65535
maxnoofMeasurementValue INTEGER ::= 2147483647
maxnoofConditionInfo INTEGER ::= 32768
maxnoofUEID INTEGER ::= 65535
maxnoofConditionInfoPerSub INTEGER ::= 32768
maxnoofUEIDPerSub INTEGER ::= 65535
maxnoofUEMeasReport INTEGER ::= 65535
MeasurementInfoList ::= SEQUENCE (SIZE(1..maxnoofMeasurementInfo)) OF MeasurementInfoItem
MeasurementInfoItem ::= SEQUENCE {
measType MeasurementType,
labelInfoList LabelInfoList,
...
}
LabelInfoList ::= SEQUENCE (SIZE(1..maxnoofLabelInfo)) OF LabelInfoItem
LabelInfoItem ::= SEQUENCE {
measLabel MeasurementLabel,
...
}
MeasurementData ::= SEQUENCE (SIZE(1..maxnoofMeasurementRecord)) OF MeasurementDataItem
MeasurementDataItem ::= SEQUENCE {
measRecord MeasurementRecord,
incompleteFlag ENUMERATED {true, ...} OPTIONAL,
...
}
MeasurementRecord ::= SEQUENCE (SIZE(1..maxnoofMeasurementValue)) OF MeasurementRecordItem
MeasurementRecordItem ::= CHOICE {
integer INTEGER (0.. 4294967295),
real REAL,
noValue NULL,
...
}
MeasurementInfo-Action-List ::= SEQUENCE (SIZE(1..maxnoofMeasurementInfo)) OF MeasurementInfo-Action-Item
MeasurementInfo-Action-Item ::= SEQUENCE {
measName MeasurementTypeName,
measID MeasurementTypeID OPTIONAL,
...
}
MeasurementCondList ::= SEQUENCE (SIZE(1..maxnoofMeasurementInfo)) OF MeasurementCondItem
MeasurementCondItem ::= SEQUENCE {
measType MeasurementType,
matchingCond MatchingCondList,
...
}
MeasurementCondUEidList ::= SEQUENCE (SIZE(1..maxnoofMeasurementInfo)) OF MeasurementCondUEidItem
MeasurementCondUEidItem ::= SEQUENCE {
measType MeasurementType,
matchingCond MatchingCondList,
matchingUEidList MatchingUEidList OPTIONAL,
...
}
MatchingCondList ::= SEQUENCE (SIZE(1..maxnoofConditionInfo)) OF MatchingCondItem
MatchingCondItem ::= CHOICE{
measLabel MeasurementLabel,
testCondInfo TestCondInfo,
...
}
MatchingUEidList ::= SEQUENCE (SIZE(1..maxnoofUEID)) OF MatchingUEidItem
MatchingUEidItem ::= SEQUENCE{
ueID UEID,
...
}
MatchingUeCondPerSubList ::= SEQUENCE (SIZE(1..maxnoofConditionInfoPerSub)) OF MatchingUeCondPerSubItem
MatchingUeCondPerSubItem ::= SEQUENCE{
testCondInfo TestCondInfo,
...
}
MatchingUEidPerSubList ::= SEQUENCE (SIZE(2..maxnoofUEIDPerSub)) OF MatchingUEidPerSubItem
MatchingUEidPerSubItem ::= SEQUENCE{
ueID UEID,
...
}
UEMeasurementReportList ::= SEQUENCE (SIZE(1..maxnoofUEMeasReport)) OF UEMeasurementReportItem
UEMeasurementReportItem ::= SEQUENCE{
ueID UEID,
measReport E2SM-KPM-IndicationMessage-Format1,
...
}
-- **************************************************************
-- E2SM-KPM Service Model IEs
-- **************************************************************
-- **************************************************************
-- Event Trigger Definition OCTET STRING contents
-- **************************************************************
E2SM-KPM-EventTriggerDefinition ::= SEQUENCE{
eventDefinition-formats CHOICE{
eventDefinition-Format1 E2SM-KPM-EventTriggerDefinition-Format1,
...
},
...
}
E2SM-KPM-EventTriggerDefinition-Format1 ::= SEQUENCE{
reportingPeriod INTEGER (1.. 4294967295),
...
}
-- **************************************************************
-- Action Definition OCTET STRING contents
-- **************************************************************
E2SM-KPM-ActionDefinition ::= SEQUENCE{
ric-Style-Type RIC-Style-Type,
actionDefinition-formats CHOICE{
actionDefinition-Format1 E2SM-KPM-ActionDefinition-Format1,
actionDefinition-Format2 E2SM-KPM-ActionDefinition-Format2,
actionDefinition-Format3 E2SM-KPM-ActionDefinition-Format3,
...,
actionDefinition-Format4 E2SM-KPM-ActionDefinition-Format4,
actionDefinition-Format5 E2SM-KPM-ActionDefinition-Format5
},
...
}
E2SM-KPM-ActionDefinition-Format1 ::= SEQUENCE {
measInfoList MeasurementInfoList,
granulPeriod GranularityPeriod,
cellGlobalID CGI OPTIONAL,
...
}
E2SM-KPM-ActionDefinition-Format2 ::= SEQUENCE {
ueID UEID,
subscriptInfo E2SM-KPM-ActionDefinition-Format1,
...
}
E2SM-KPM-ActionDefinition-Format3 ::= SEQUENCE {
measCondList MeasurementCondList,
granulPeriod GranularityPeriod,
cellGlobalID CGI OPTIONAL,
...
}
E2SM-KPM-ActionDefinition-Format4 ::= SEQUENCE {
matchingUeCondList MatchingUeCondPerSubList,
subscriptionInfo E2SM-KPM-ActionDefinition-Format1,
...
}
E2SM-KPM-ActionDefinition-Format5 ::= SEQUENCE {
matchingUEidList MatchingUEidPerSubList,
subscriptionInfo E2SM-KPM-ActionDefinition-Format1,
...
}
-- **************************************************************
-- Indication Header OCTET STRING contents
-- **************************************************************
E2SM-KPM-IndicationHeader ::= SEQUENCE{
indicationHeader-formats CHOICE{
indicationHeader-Format1 E2SM-KPM-IndicationHeader-Format1,
...
},
...
}
E2SM-KPM-IndicationHeader-Format1 ::= SEQUENCE{
colletStartTime TimeStamp,
fileFormatversion PrintableString (SIZE (0..15), ...) OPTIONAL,
senderName PrintableString (SIZE (0..400), ...) OPTIONAL,
senderType PrintableString (SIZE (0..8), ...) OPTIONAL,
vendorName PrintableString (SIZE (0..32), ...) OPTIONAL,
...
}
-- **************************************************************
-- Indication Message OCTET STRING contents
-- **************************************************************
E2SM-KPM-IndicationMessage ::= SEQUENCE{
indicationMessage-formats CHOICE{
indicationMessage-Format1 E2SM-KPM-IndicationMessage-Format1,
indicationMessage-Format2 E2SM-KPM-IndicationMessage-Format2,
...,
indicationMessage-Format3 E2SM-KPM-IndicationMessage-Format3
},
...
}
E2SM-KPM-IndicationMessage-Format1 ::= SEQUENCE {
measData MeasurementData,
measInfoList MeasurementInfoList OPTIONAL,
granulPeriod GranularityPeriod OPTIONAL,
...
}
E2SM-KPM-IndicationMessage-Format2 ::= SEQUENCE {
measData MeasurementData,
measCondUEidList MeasurementCondUEidList,
granulPeriod GranularityPeriod OPTIONAL,
...
}
E2SM-KPM-IndicationMessage-Format3 ::= SEQUENCE {
ueMeasReportList UEMeasurementReportList,
...
}
-- ***************************************************************
-- RAN Function Definition OCTET STRING contents
-- ***************************************************************
E2SM-KPM-RANfunction-Description ::= SEQUENCE{
ranFunction-Name RANfunction-Name,
ric-EventTriggerStyle-List SEQUENCE (SIZE(1..maxnoofRICStyles)) OF RIC-EventTriggerStyle-Item OPTIONAL,
ric-ReportStyle-List SEQUENCE (SIZE(1..maxnoofRICStyles)) OF RIC-ReportStyle-Item OPTIONAL,
...
}
RIC-EventTriggerStyle-Item ::= SEQUENCE{
ric-EventTriggerStyle-Type RIC-Style-Type,
ric-EventTriggerStyle-Name RIC-Style-Name,
ric-EventTriggerFormat-Type RIC-Format-Type,
...
}
RIC-ReportStyle-Item ::= SEQUENCE{
ric-ReportStyle-Type RIC-Style-Type,
ric-ReportStyle-Name RIC-Style-Name,
ric-ActionFormat-Type RIC-Format-Type,
measInfo-Action-List MeasurementInfo-Action-List,
ric-IndicationHeaderFormat-Type RIC-Format-Type,
ric-IndicationMessageFormat-Type RIC-Format-Type,
...
}
END
-- ASN1STOP

View File

@ -0,0 +1,388 @@
-- ASN1START
-- **************************************************************
-- E2SM
-- Information Element Definitions
-- N.B. this is an edited version, only supplying what is needed for KPM-v2
-- **************************************************************
E2SM-COMMON-IEs {
iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) 53148 e2(1) version1 (1) e2sm(2) e2sm-COMMON-IEs (0)}
DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
-- --------------------------------------------------
-- Constants
-- --------------------------------------------------
maxE1APid INTEGER ::= 65535
maxF1APid INTEGER ::= 4
-- IEs derived from 3GPP 36.423 (X2AP)
maxEARFCN INTEGER ::= 65535
-- IEs derived from 3GPP 38.473 (F1AP)
maxNRARFCN INTEGER ::= 3279165
maxnoofNrCellBands INTEGER ::= 32
-- --------------------------------------------------
-- E2SM Commmon IEs
-- --------------------------------------------------
CGI ::= CHOICE {
nR-CGI NR-CGI,
eUTRA-CGI EUTRA-CGI,
...
}
RANfunction-Name ::= SEQUENCE{
ranFunction-ShortName PrintableString(SIZE(1..150,...)),
ranFunction-E2SM-OID PrintableString(SIZE(1..1000,...)),
ranFunction-Description PrintableString(SIZE(1..150,...)),
ranFunction-Instance INTEGER OPTIONAL,
...
}
RIC-Format-Type ::= INTEGER
RIC-Style-Type ::= INTEGER
RIC-Style-Name ::= PrintableString(SIZE(1..150,...))
UEID ::= CHOICE{
gNB-UEID UEID-GNB,
gNB-DU-UEID UEID-GNB-DU,
gNB-CU-UP-UEID UEID-GNB-CU-UP,
ng-eNB-UEID UEID-NG-ENB,
ng-eNB-DU-UEID UEID-NG-ENB-DU,
en-gNB-UEID UEID-EN-GNB,
eNB-UEID UEID-ENB,
...
}
UEID-GNB ::= SEQUENCE{
amf-UE-NGAP-ID AMF-UE-NGAP-ID,
guami GUAMI,
gNB-CU-UE-F1AP-ID-List UEID-GNB-CU-F1AP-ID-List OPTIONAL,
-- C-ifCUDUseparated: This IE shall be present in messages from E2 Node to NearRT-RIC for a CU-DU separated gNB, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. More than 1 F1AP ID shall be reported by E2 Node only when NR-DC is established.
gNB-CU-CP-UE-E1AP-ID-List UEID-GNB-CU-CP-E1AP-ID-List OPTIONAL,
-- C-ifCPUPseparated: This IE shall be present in messages from E2 Node to NearRT-RIC for a CP-UP separated gNB, whereas from NearRT-RIC to E2 Node messages, this IE may not be included.
ran-UEID RANUEID OPTIONAL,
m-NG-RAN-UE-XnAP-ID NG-RANnodeUEXnAPID OPTIONAL,
-- C-ifDCSetup: This IE shall be present in messages from E2 Node to NearRT-RIC if DC is established, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. To be reported by both MN and SN.
globalGNB-ID GlobalGNB-ID OPTIONAL,
-- This IE shall not be used. This IE is replaced with globalNG-RANNode-ID.
...,
globalNG-RANNode-ID GlobalNGRANNodeID OPTIONAL
-- C-ifDCSetup: This IE shall be present in messages from E2 Node to NearRT-RIC if DC is established, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. To be reported only by SN.
}
UEID-GNB-CU-CP-E1AP-ID-List ::= SEQUENCE (SIZE(1..maxE1APid)) OF UEID-GNB-CU-CP-E1AP-ID-Item
UEID-GNB-CU-CP-E1AP-ID-Item ::= SEQUENCE{
gNB-CU-CP-UE-E1AP-ID GNB-CU-CP-UE-E1AP-ID,
...
}
UEID-GNB-CU-F1AP-ID-List ::= SEQUENCE (SIZE(1..maxF1APid)) OF UEID-GNB-CU-CP-F1AP-ID-Item
UEID-GNB-CU-CP-F1AP-ID-Item ::= SEQUENCE{
gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID,
...
}
UEID-GNB-DU ::= SEQUENCE{
gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID,
ran-UEID RANUEID OPTIONAL,
...
}
UEID-GNB-CU-UP ::= SEQUENCE{
gNB-CU-CP-UE-E1AP-ID GNB-CU-CP-UE-E1AP-ID,
ran-UEID RANUEID OPTIONAL,
...
}
UEID-NG-ENB ::= SEQUENCE{
amf-UE-NGAP-ID AMF-UE-NGAP-ID,
guami GUAMI,
ng-eNB-CU-UE-W1AP-ID NGENB-CU-UE-W1AP-ID OPTIONAL,
-- C-ifCUDUseperated: This IE shall be present in messages from E2 Node to NearRT-RIC for a CU-DU seperated ng-eNB, whereas from NearRT-RIC to E2 Node messages, this IE may not be included.
m-NG-RAN-UE-XnAP-ID NG-RANnodeUEXnAPID OPTIONAL,
-- C-ifDCSetup: This IE shall be present in messages from E2 Node to NearRT-RIC if DC is established, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. To be reported by both MN and SN.
globalNgENB-ID GlobalNgENB-ID OPTIONAL,
-- This IE shall not be used. This IE is replaced with globalNG-RANNode-ID.
...,
globalNG-RANNode-ID GlobalNGRANNodeID OPTIONAL
-- C-ifDCSetup: This IE shall be present in messages from E2 Node to NearRT-RIC if DC is established, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. To be reported only by SN.
}
UEID-NG-ENB-DU ::= SEQUENCE{
ng-eNB-CU-UE-W1AP-ID NGENB-CU-UE-W1AP-ID,
...
}
UEID-EN-GNB ::= SEQUENCE{
m-eNB-UE-X2AP-ID ENB-UE-X2AP-ID,
m-eNB-UE-X2AP-ID-Extension ENB-UE-X2AP-ID-Extension OPTIONAL,
globalENB-ID GlobalENB-ID,
gNB-CU-UE-F1AP-ID GNB-CU-UE-F1AP-ID OPTIONAL,
-- C-ifCUDUseperated: This IE shall be present in messages from E2 Node to NearRT-RIC for a CU-DU seperated en-gNB, whereas from NearRT-RIC to E2 Node messages, this IE may not be included.
gNB-CU-CP-UE-E1AP-ID-List UEID-GNB-CU-CP-E1AP-ID-List OPTIONAL,
-- C-ifCPUPseparated: This IE shall be present in messages from E2 Node to NearRT-RIC for a CP-UP separated en-gNB, whereas from NearRT-RIC to E2 Node messages, this IE may not be included.
ran-UEID RANUEID OPTIONAL,
...
}
UEID-ENB ::= SEQUENCE{
mME-UE-S1AP-ID MME-UE-S1AP-ID,
gUMMEI GUMMEI,
m-eNB-UE-X2AP-ID ENB-UE-X2AP-ID OPTIONAL,
-- This IE shall be present in messages from E2 Node to NearRT-RIC if DC is established, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. To be reported by MeNB and SeNB.
m-eNB-UE-X2AP-ID-Extension ENB-UE-X2AP-ID-Extension OPTIONAL,
globalENB-ID GlobalENB-ID OPTIONAL,
-- This IE shall be present in messages from E2 Node to NearRT-RIC if DC is established, whereas from NearRT-RIC to E2 Node messages, this IE may not be included. To be reported only by SeNB.
...
}
-- **************************************************************
-- 3GPP derived IEs
-- **************************************************************
-- NOTE:
-- - Extension fields removed and replaced with "..."
-- - IE names modified across all extracts to use "PLMNIdentity"
-- **************************************************************
-- IEs derived from 3GPP 36.413 (S1AP)
-- **************************************************************
-- **************************************************************
-- copied from v16.5.0
ENB-ID ::= CHOICE {
macro-eNB-ID BIT STRING (SIZE (20)),
home-eNB-ID BIT STRING (SIZE (28)),
... ,
short-Macro-eNB-ID BIT STRING (SIZE(18)),
long-Macro-eNB-ID BIT STRING (SIZE(21))
}
-- copied from v16.5.0
GlobalENB-ID ::= SEQUENCE {
pLMNIdentity PLMNIdentity,
eNB-ID ENB-ID,
...
}
-- copied from v16.5.0
GUMMEI ::= SEQUENCE {
pLMN-Identity PLMNIdentity,
mME-Group-ID MME-Group-ID,
mME-Code MME-Code,
...
}
-- copied from v16.5.0
MME-Group-ID ::= OCTET STRING (SIZE (2))
-- copied from v16.5.0
MME-Code ::= OCTET STRING (SIZE (1))
-- copied from v16.5.0
MME-UE-S1AP-ID ::= INTEGER (0..4294967295)
-- copied from v16.5.0
QCI ::= INTEGER (0..255)
-- **************************************************************
-- IEs derived from 3GPP 36.423 (X2AP)
-- **************************************************************
-- Extension fields removed.
-- Note: to avoid duplicate names with NGAP, XnAP, etc.:
-- GNB-ID renamed ENGNB-ID,
-- GlobalGNB-ID renamed GlobalenGNB-ID,
-- UE-X2AP-ID renamed ENB-UE-X2AP-ID
-- UE-X2AP-ID-Extension renamed ENB-UE-X2AP-ID-Extension
-- **************************************************************
-- copied from v16.5.0
ENB-UE-X2AP-ID ::= INTEGER (0..4095)
-- copied from v16.5.0
ENB-UE-X2AP-ID-Extension ::= INTEGER (0..4095, ...)
-- **************************************************************
-- IEs derived from 3GPP 37.473 (W1AP)
-- **************************************************************
-- copied from v16.3.0
NGENB-CU-UE-W1AP-ID ::= INTEGER (0..4294967295)
-- **************************************************************
-- IEs derived from 3GPP 38.413 (NGAP)
-- Extension fields removed and replaced with ...
-- **************************************************************
-- copied from v16.2.0
AMFPointer ::= BIT STRING (SIZE(6))
-- copied from v16.2.0
AMFRegionID ::= BIT STRING (SIZE(8))
-- copied from v16.2.0
AMFSetID ::= BIT STRING (SIZE(10))
-- copied from v16.2.0
AMF-UE-NGAP-ID ::= INTEGER (0..1099511627775)
-- copied from v16.2.0
EUTRACellIdentity ::= BIT STRING (SIZE(28))
-- copied from v16.2.0
EUTRA-CGI ::= SEQUENCE {
pLMNIdentity PLMNIdentity,
eUTRACellIdentity EUTRACellIdentity,
...
}
-- copied from v16.2.0
FiveQI ::= INTEGER (0..255, ...)
-- copied from v16.2.0
GlobalGNB-ID ::= SEQUENCE {
pLMNIdentity PLMNIdentity,
gNB-ID GNB-ID,
...
}
-- copied from v16.2.0
GlobalNgENB-ID ::= SEQUENCE {
pLMNIdentity PLMNIdentity,
ngENB-ID NgENB-ID,
...
}
-- copied from v16.2.0
GNB-ID ::= CHOICE {
gNB-ID BIT STRING (SIZE(22..32)),
...
}
-- copied from v16.2.0
GUAMI ::= SEQUENCE {
pLMNIdentity PLMNIdentity,
aMFRegionID AMFRegionID,
aMFSetID AMFSetID,
aMFPointer AMFPointer,
...
}
-- copied from v16.2.0
NgENB-ID ::= CHOICE {
macroNgENB-ID BIT STRING (SIZE(20)),
shortMacroNgENB-ID BIT STRING (SIZE(18)),
longMacroNgENB-ID BIT STRING (SIZE(21)),
...
}
-- copied from v16.2.0
NRCellIdentity ::= BIT STRING (SIZE(36))
-- copied from v16.2.0
NR-CGI ::= SEQUENCE {
pLMNIdentity PLMNIdentity,
nRCellIdentity NRCellIdentity,
...
}
-- copied from v16.2.0
PLMNIdentity ::= OCTET STRING (SIZE(3))
-- copied from v16.2.0
QosFlowIdentifier ::= INTEGER (0..63, ...)
-- copied from v16.2.0
SD ::= OCTET STRING (SIZE(3))
-- copied from v16.2.0
S-NSSAI ::= SEQUENCE {
sST SST,
sD SD OPTIONAL,
...
}
-- copied from v16.2.0
SST ::= OCTET STRING (SIZE(1))
-- **************************************************************
-- IEs derived from 3GPP 38.423 (XnAP)
-- **************************************************************
-- copied from v16.2.0
NG-RANnodeUEXnAPID ::= INTEGER (0.. 4294967295)
GlobalNGRANNodeID ::= CHOICE {
gNB GlobalGNB-ID,
ng-eNB GlobalNgENB-ID,
...
}
-- **************************************************************
-- IEs derived from 3GPP 37.483 (E1AP)
-- **************************************************************
-- copied from v17.1.0
GNB-CU-CP-UE-E1AP-ID ::= INTEGER (0..4294967295)
-- copied from v17.1.0
-- GNB-CU-UP-ID ::= INTEGER (0..68719476735)
-- **************************************************************
-- IEs derived from 3GPP 38.473 (F1AP)
-- **************************************************************
-- copied from v16.5.0
GNB-CU-UE-F1AP-ID ::= INTEGER (0..4294967295)
-- copied from v16.5.0
RANUEID ::= OCTET STRING (SIZE (8))
END
-- ASN1STOP

View File

@ -0,0 +1,77 @@
# kpm-v2.cnf
# kpm-v2 conformation file
#.OPT
PER
ALIGNED
#.END
#.USE_VALS_EXT
#.EXPORTS ONLY_VALS WS_DLL
#.EXPORTS
#.PDU
E2SM-KPM-EventTriggerDefinition
E2SM-KPM-ActionDefinition
E2SM-KPM-IndicationHeader
E2SM-KPM-IndicationMessage
E2SM-KPM-RANfunction-Description
#.MAKE_ENUM
#.NO_EMIT
#.OMIT_ASSIGNMENT
#.END
#.TYPE_ATTR
#.TYPE_RENAME
#.FIELD_RENAME
#.FIELD_ATTR
#.ASSIGN_VALUE_TO_TYPE
#.END
#.REGISTER
#.FN_BODY RANfunction-Name/ranFunction-ShortName VAL_PTR=&value_tvb
tvbuff_t *value_tvb;
%(DEFAULT_BODY)s
if (!actx->pinfo->fd->visited) {
/* N.B. too early to work out exact dissector, as don't have OID yet */
e2ap_store_ran_function_mapping(actx->pinfo,
tvb_get_string_enc(wmem_packet_scope(), value_tvb, 0, tvb_captured_length(value_tvb), ENC_ASCII));
}
#.FN_BODY RANfunction-Name/ranFunction-E2SM-OID VAL_PTR = &parameter_tvb
tvbuff_t *parameter_tvb;
%(DEFAULT_BODY)s
e2ap_update_ran_function_mapping(actx->pinfo, tree, parameter_tvb,
tvb_get_string_enc(actx->pinfo->pool, parameter_tvb, 0,
tvb_captured_length(parameter_tvb), ENC_ASCII));
#
# Editor modelines - https://www.wireshark.org/tools/modelines.html
#
# Local variables:
# c-basic-offset: 2
# tab-width: 8
# indent-tabs-mode: nil
# End:
#
# vi: set shiftwidth=2 tabstop=8 expandtab:
# :indentSize=2:tabSize=8:noTabs=true:
#

View File

@ -0,0 +1,114 @@
/* packet-kpm-v2-template.c
* Copyright 2021, Martin Mathieson
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* References: ORAN-WG3.E2SM-KPM-v02.02
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/strutil.h>
#include <epan/asn1.h>
#include "packet-e2ap.h"
#include "packet-per.h"
#define PNAME "KPM V2"
#define PSNAME "KPMv2"
#define PFNAME "kpm-v2"
void proto_register_kpm_v2(void);
void proto_reg_handoff_kpm_v2(void);
#include "packet-kpm-v2-val.h"
/* Initialize the protocol and registered fields */
static int proto_kpm_v2 = -1;
#include "packet-kpm-v2-hf.c"
#include "packet-kpm-v2-ett.c"
/* Forward declarations */
static int dissect_E2SM_KPM_EventTriggerDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_KPM_ActionDefinition_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_KPM_IndicationHeader_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_KPM_IndicationMessage_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
static int dissect_E2SM_KPM_RANfunction_Description_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_);
#include "packet-kpm-v2-fn.c"
/*--- proto_reg_handoff_kpm_v2 ---------------------------------------*/
void
proto_reg_handoff_kpm_v2(void)
{
//#include "packet-kpm-v2-dis-tab.c"
static ran_function_dissector_t kpm_v2 =
{ "ORAN-E2SM-KPM", "1.3.6.1.4.1.53148.1.2.2.2", 2, 2,
{ dissect_E2SM_KPM_RANfunction_Description_PDU,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
dissect_E2SM_KPM_ActionDefinition_PDU,
dissect_E2SM_KPM_IndicationMessage_PDU,
dissect_E2SM_KPM_IndicationHeader_PDU,
NULL, /* no dissect_E2SM_KPM_CallProcessID_PDU */
dissect_E2SM_KPM_EventTriggerDefinition_PDU
}
};
/* Register dissector with e2ap */
register_e2ap_ran_function_dissector(KPM_RANFUNCTIONS, &kpm_v2);
}
/*--- proto_register_kpm_v2 -------------------------------------------*/
void proto_register_kpm_v2(void) {
/* List of fields */
static hf_register_info hf[] = {
#include "packet-kpm-v2-hfarr.c"
};
/* List of subtrees */
static gint *ett[] = {
#include "packet-kpm-v2-ettarr.c"
};
/* Register protocol */
proto_kpm_v2 = proto_register_protocol(PNAME, PSNAME, PFNAME);
/* Register fields and subtrees */
proto_register_field_array(proto_kpm_v2, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 2
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,51 @@
/*--- End of included file: packet-e2ap-exp.h ---*/
#line 15 "./asn1/e2ap/packet-e2ap-template.h"
typedef int (*pdu_dissector_t)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
/* Function pointers for a RANFunction */
typedef struct {
pdu_dissector_t ran_function_definition_dissector;
pdu_dissector_t ric_control_header_dissector;
pdu_dissector_t ric_control_message_dissector;
pdu_dissector_t ric_control_outcome_dissector;
/* new for v3 */
pdu_dissector_t ric_query_outcome_dissector;
pdu_dissector_t ric_query_definition_dissector;
pdu_dissector_t ric_query_header_dissector;
pdu_dissector_t ran_action_definition_dissector;
pdu_dissector_t ran_indication_message_dissector;
pdu_dissector_t ran_indication_header_dissector;
pdu_dissector_t ran_callprocessid_dissector;
pdu_dissector_t ran_event_trigger_dissector;
} ran_function_pointers_t;
typedef enum {
MIN_RANFUNCTIONS,
KPM_RANFUNCTIONS=0,
RC_RANFUNCTIONS,
NI_RANFUNCTIONS,
MAX_RANFUNCTIONS
} ran_function_t;
#define MAX_OID_LEN 1001
typedef struct {
const char* name;
char oid[MAX_OID_LEN]; /* i.e., this dissector */
uint8_t major_version;
uint8_t minor_version;
ran_function_pointers_t functions;
} ran_function_dissector_t;
void register_e2ap_ran_function_dissector(ran_function_t ran_function, ran_function_dissector_t *dissector);
void e2ap_store_ran_function_mapping(packet_info *pinfo, const char *name);
void e2ap_update_ran_function_mapping(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, const char *oid);
#endif /* PACKET_E2AP_H */
/*

File diff suppressed because it is too large Load Diff

View File

@ -899,6 +899,7 @@ char* rel_oid_subid2string(wmem_allocator_t *scope, guint32* subids, guint len,
return wmem_strbuf_finalize(oid_str);
}
/* If a valid OID string, return number of numbers */
static guint check_num_oid(const char* str) {
const char* r = str;
char c = '.';
@ -925,6 +926,7 @@ static guint check_num_oid(const char* str) {
return n;
}
/* Set subids_p to an array of found numbers, return number of numbers */
guint oid_string2subid(wmem_allocator_t *scope, const char* str, guint32** subids_p) {
const char* r = str;
guint32* subids;