From a479218813aeaf6eb2c1431cdcdc3cc92266d9ad Mon Sep 17 00:00:00 2001 From: onehouwong Date: Thu, 14 Mar 2024 23:20:46 -0400 Subject: [PATCH] encode action def test --- src/asn1/AsnProxy.py | 2 +- src/asn1/wrapper.c | 177 +++++++++++++++++++++++++---- src/hwxapp.py | 11 +- src/manager/SubscriptionManager.py | 26 +++-- 4 files changed, 175 insertions(+), 41 deletions(-) diff --git a/src/asn1/AsnProxy.py b/src/asn1/AsnProxy.py index e3d8167..c72cf84 100644 --- a/src/asn1/AsnProxy.py +++ b/src/asn1/AsnProxy.py @@ -8,7 +8,7 @@ class AsnProxy(ABC): def __init__(self, path_wrapper_c_exec): self.wrapper_path = path_wrapper_c_exec - def encode_asn_struct(self, structure_name: str, hex_str: str) -> dict: + def encode_asn_struct(self, structure_name: str, hex_str: str) -> str: # Call the C program with the specified operation, structure name, and payload # operation = "encode" # result = subprocess.run([self.wrapper_path, operation, structure_name, hex_str], capture_output=True, text=True) diff --git a/src/asn1/wrapper.c b/src/asn1/wrapper.c index bca22c0..2a8e031 100644 --- a/src/asn1/wrapper.c +++ b/src/asn1/wrapper.c @@ -4,15 +4,24 @@ #include "E2SM-KPMv2-IndicationMessage.h" #include "E2SM-KPMv2-ActionDefinition.h" #include "E2SM-KPMv2-RANfunction-Description.h" +#include "E2SM-KPMv2-ActionDefinition-Format1.h" +#include "GranularityPeriod-KPMv2.h" +#include "SubscriptionID-KPMv2.h" +#include "CellObjectID-KPMv2.h" +#include "MeasurementInfoList-KPMv2.h" +#include "MeasurementInfoItem-KPMv2.h" +#include "MeasurementType-KPMv2.h" -// Function to encode ASN.1 data structure -void encode_data_structure(const char* structure_name, const char* binary_payload, size_t len) { - // Encode the ASN.1 data structure - // Write encoded data to stdout - printf("Encoded data\n"); -} +void decode_data_structure(const char* structure_name, const char* hex_payload) { + // Convert hex payload to binary + size_t hex_len = strlen(hex_payload); + size_t bin_len = hex_len / 2; + char* binary_payload = (char*)malloc(bin_len + 1); + for (size_t i = 0; i < bin_len; i++) { + sscanf(hex_payload + 2 * i, "%2hhx", &binary_payload[i]); + } + binary_payload[bin_len] = '\0'; -void decode_data_structure(const char* structure_name, const char* binary_payload, size_t len) { // Decode the ASN.1 data structure // Write decoded data to stdout enum asn_transfer_syntax syntax = ATS_ALIGNED_BASIC_PER; @@ -41,7 +50,7 @@ void decode_data_structure(const char* structure_name, const char* binary_payloa } // Decode the structure - decode_result = asn_decode(0, syntax, structure_mapping[i].type, &struct_ins, binary_payload, len); + decode_result = asn_decode(0, syntax, structure_mapping[i].type, &struct_ins, binary_payload, bin_len); if (decode_result.code != RC_OK) { fprintf(stderr, "Failed to decode structure: %s, error code: %d\n", structure_mapping[i].name, decode_result.code); return; @@ -60,29 +69,155 @@ void decode_data_structure(const char* structure_name, const char* binary_payloa fprintf(stderr, "Unknown structure name: %s\n", structure_name); } +// Function to convert binary data to hex string +char* binary_to_hex_string(const uint8_t* binary_data, size_t data_len) { + // Allocate memory for the hex string + char *hex_string = (char*)malloc(data_len * 2 + 1); // Two hex characters per byte, plus one for null terminator + if (hex_string == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + return NULL; + } + + // Convert each byte to hex + for (size_t i = 0; i < data_len; i++) { + sprintf(&hex_string[i * 2], "%02X", binary_data[i]); + } + hex_string[data_len * 2] = '\0'; // Null-terminate the string + + return hex_string; +} + +// Function to encode action definition +void encode_action_definition(int format, long ricStyleType, char* cellObjID, long granularityPeriod, long subId, char* measList) { + E2SM_KPMv2_ActionDefinition_t *actionDef = (E2SM_KPMv2_ActionDefinition_t *) calloc(1, sizeof(E2SM_KPMv2_ActionDefinition_t)); + E2SM_KPMv2_ActionDefinition_Format1_t *actionDefFormat1; + + if (!actionDef) { + fprintf(stderr, "alloc RIC ActionDefinition failed\n"); + return; + } + + // ric style + actionDef->ric_Style_Type = ricStyleType; + + // currently only support format 1 + if (format == 1) { + actionDefFormat1 = (E2SM_KPMv2_ActionDefinition_Format1_t *)calloc(1, sizeof(E2SM_KPMv2_ActionDefinition_Format1_t)); + + // cellObjID + actionDefFormat1->cellObjID.buf = (uint8_t *)strdup(cellObjID); + actionDefFormat1->cellObjID.size = strlen(cellObjID); + + // granularity period + actionDefFormat1->granulPeriod = granularityPeriod; + + // subscription ID + SubscriptionID_KPMv2_t g_subscriptionID; + actionDefFormat1->subscriptID = subId; + + // measurement items + MeasurementInfoItem_KPMv2_t* actionDefMeasInfoItem; + int measItemSize = 0; + const char *delimiter = ";"; // assume the delimiter is ";" + char *token = strtok(measList, delimiter); + while(token != NULL) { + actionDefMeasInfoItem = (MeasurementInfoItem_KPMv2_t *)calloc(1, sizeof(MeasurementInfoItem_KPMv2_t)); + actionDefMeasInfoItem->measType.present = MeasurementType_KPMv2_PR_measName; + actionDefMeasInfoItem->measType.choice.measName.buf = (uint8_t *)strdup(token); + actionDefMeasInfoItem->measType.choice.measName.size = strlen(token); + ASN_SEQUENCE_ADD(&actionDefFormat1->measInfoList, actionDefMeasInfoItem); + ++measItemSize; + token = strtok(NULL, delimiter); + } + actionDefFormat1->measInfoList.list.count = measItemSize; + + actionDef->actionDefinition_formats.present = E2SM_KPMv2_ActionDefinition__actionDefinition_formats_PR_actionDefinition_Format1; + actionDef->actionDefinition_formats.choice.actionDefinition_Format1 = actionDefFormat1; + } + + // encode + uint8_t e2smbuffer[8192]; + size_t e2smbuffer_size = 8192; + asn_enc_rval_t er = asn_encode_to_buffer(NULL, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2SM_KPMv2_ActionDefinition, + actionDef, e2smbuffer, e2smbuffer_size); + + if (er.encoded < 0) { + fprintf(stderr, "Encode failure for E2SM_KPMv2_ActionDefinition, name=%s, tag=%s\n", er.failed_type->name, er.failed_type->xml_tag); + } + else { + fprintf(stderr, "Encode successful for E2SM_KPMv2_ActionDefinition, encoded bytes=%ld\n", er.encoded); + char *hex_string = binary_to_hex_string(e2smbuffer, er.encoded); + printf("%s\n", hex_string); + xer_fprint(stdout, &asn_DEF_E2SM_KPMv2_ActionDefinition, actionDef); + } + + free(actionDefFormat1); + free(actionDef); +} + +// Function to encode ASN.1 data structure +void encode_data_structure(const char* structure_name, const char* payload) { + // Encode the ASN.1 data structure + // Write encoded data to stdout + char *copiedPayload = strdup(payload); + if (strcmp(structure_name, "E2SM_KPMv2_ActionDefinition") == 0) { + const char *delimiter = ","; // this need to be consistent with the python part... + int index = 0; + int format; + long ricStyleType, granularityPeriod, subId; + char *cellObjID, *measList; + char *token = strtok(copiedPayload, delimiter); + while(token != NULL) { + switch (index) { + case 0: + format = atoi(token); + break; + case 1: + ricStyleType = atol(token); + break; + case 2: + cellObjID = strdup(token); + break; + case 3: + granularityPeriod = atol(token); + break; + case 4: + subId = atol(token); + break; + case 5: + measList = strdup(token); + break; + default: + break; + } + ++index; + token = strtok(NULL, delimiter); + } + if (index != 6) { + fprintf(stderr, "Incorrect arg num for encoding E2SM_KPMv2_ActionDefinition: %d\n", index); + } + encode_action_definition(format, ricStyleType, cellObjID, granularityPeriod, subId, measList); + } + + free(copiedPayload); +} + + int main(int argc, char *argv[]) { + if (argc < 4) { - printf("Usage: %s \n", argv[0]); + printf("Usage: %s \n", argv[0]); return 1; } const char* operation = argv[1]; const char* structure_name = argv[2]; - const char* hex_payload = argv[3]; - - // Convert hex payload to binary - size_t hex_len = strlen(hex_payload); - size_t bin_len = hex_len / 2; - char* binary_payload = (char*)malloc(bin_len + 1); - for (size_t i = 0; i < bin_len; i++) { - sscanf(hex_payload + 2 * i, "%2hhx", &binary_payload[i]); - } - binary_payload[bin_len] = '\0'; + const char* payload = argv[3]; if (strcmp(operation, "encode") == 0) { - encode_data_structure(structure_name, binary_payload, bin_len); + encode_data_structure(structure_name, payload); } else if (strcmp(operation, "decode") == 0) { - decode_data_structure(structure_name, binary_payload, bin_len); + decode_data_structure(structure_name, payload); } else { printf("Invalid operation\n"); return 1; diff --git a/src/hwxapp.py b/src/hwxapp.py index 930cb0d..80f5f7d 100644 --- a/src/hwxapp.py +++ b/src/hwxapp.py @@ -84,22 +84,13 @@ def _post_init(self, rmr_xapp): connection_status = gnb_nb_identity.connection_status nodeb_info_json = self.sdl_mgr.get_nodeb_info_by_inventory_name(inventory_name) for ran_func in nodeb_info_json["gnb"]["ranFunctions"]: - rf_id = ran_func["ranFunctionId"] - rf_def = ran_func["ranFunctionDefinition"] rf_oid = ran_func["ranFunctionOid"] if rf_oid in TARGET_OID_LIST: rmr_xapp.logger.debug(f"Found target ran function for gNB {inventory_name}: {ran_func}") - - decoded_rf_def = self.asn_proxy.decode_e2sm_kpm_ran_function_definition(rf_def) - rmr_xapp.logger.debug(f"Decode RAN function def:\n {decoded_rf_def}") - - # subscribe_nb_list.append(gnb_nb_identity) - # break - # Subscribe to NodeB rmr_xapp.logger.debug(f"connection status {connection_status}") if connection_status == 1: - self.sub_mgr.send_subscription_request(gnb_nb_identity, rf_id) + self.sub_mgr.send_subscription_request(gnb_nb_identity, ran_func) # TODO: keep polling node b list but do not block this function diff --git a/src/manager/SubscriptionManager.py b/src/manager/SubscriptionManager.py index 27e088f..9598bca 100644 --- a/src/manager/SubscriptionManager.py +++ b/src/manager/SubscriptionManager.py @@ -30,7 +30,7 @@ from ..asn1 import AsnProxy from ._BaseManager import _BaseManager from ..mobiflow import FactBase, BS, BSMobiFlow -from ..utils import Constants +from ..utils import Constants, find_all_values from mdclogpy import Level @@ -77,8 +77,16 @@ def query_subscriptions(self): except requests.exceptions.RequestException as err: return "An Unknown Error occurred" + repr(err) - def send_subscription_request(self, nb_identity: NbIdentity, ran_function_id: int): + def send_subscription_request(self, nb_identity: NbIdentity, ran_function: dict): me_id = nb_identity.inventory_name + rf_id = ran_function["ranFunctionId"] + rf_def = ran_function["ranFunctionDefinition"] + + decoded_rf_def = self.asn_proxy.decode_e2sm_kpm_ran_function_definition(rf_def) + self.logger.debug(f"Decode RAN function def:\n {decoded_rf_def}") + kpm_measurement_names = find_all_values(decoded_rf_def, "measName") + meas_list = ";".join(kpm_measurement_names) + if me_id in self.subscription_list.keys(): return # subscription already exist subscription_params = {"ClientEndPoint": {"Host": self.__CLIENT_END_POINT, @@ -86,7 +94,7 @@ def send_subscription_request(self, nb_identity: NbIdentity, ran_function_id: in "RMRPort": self.client_rmr_port }, "Meid": me_id, - "RANFunctionID": ran_function_id, + "RANFunctionID": rf_id, "E2SubscriptionDirectives":{ "E2TimeoutTimerValue": 10, "E2RetryCount": 2, @@ -97,7 +105,7 @@ def send_subscription_request(self, nb_identity: NbIdentity, ran_function_id: in "ActionToBeSetupList": [ {"ActionID": 0, "ActionType": "report", - "ActionDefinition": self.encode_action_definition(), + "ActionDefinition": self.encode_action_definition(meas_list=meas_list), "SubsequentActionType": "continue", "TimeToWait": "w10ms"} ]}] @@ -188,11 +196,11 @@ def encode_report_period(self) -> list: # [0x08, 0x03, 0xe7], # 0x3e7 -> 1000 return [0x08, (self.report_period-1) // 256, (self.report_period-1) % 256] - def encode_action_definition(self): - # hack for now until we find ways to encode / decode ASN1, this action def is dedicated for mobiflow kpm - action_def_hex = "000600000131001D003055452E524E5449003855452E494D534931003855452E494D534932002855452E524154004055452E4D5F544D5349006055452E4349504845525F414C47007855452E494E544547524954595F414C47005855452E454D4D5F4341555345007855452E52454C454153455F54494D4552008855452E45535441424C4953485F434155534500186D73673100186D73673200186D73673300186D73673400186D73673500186D73673600186D73673700186D73673800186D73673900206D7367313000206D7367313100206D7367313200206D7367313300206D7367313400206D7367313500206D7367313600206D7367313700206D7367313800206D7367313900206D736732304003E70000" + def encode_action_definition(self, meas_list: str, action_format=1, ric_style_type=6, cell_obj_id=1, subscription_id=1): + delimiter = "," + action_def_params = delimiter.join([str(action_format), str(ric_style_type), str(cell_obj_id), str(subscription_id), meas_list]) + action_def_hex = self.asn_proxy.encode_e2sm_kpm_action_definition(action_def_params) + self.logger.debug(f"Encoded action definition hex payload: {action_def_hex}") action_def_encoded = [int(action_def_hex[i:i + 2], 16) for i in range(0, len(action_def_hex), 2)] return action_def_encoded - -