Skip to content

Commit

Permalink
encode action def test
Browse files Browse the repository at this point in the history
  • Loading branch information
onehouwong committed Mar 15, 2024
1 parent 8b2b639 commit a479218
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/asn1/AsnProxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
177 changes: 156 additions & 21 deletions src/asn1/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 <encode|decode> <structure_name> <binary_payload>\n", argv[0]);
printf("Usage: %s <encode|decode> <structure_name> <payload>\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;
Expand Down
11 changes: 1 addition & 10 deletions src/hwxapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
26 changes: 17 additions & 9 deletions src/manager/SubscriptionManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -77,16 +77,24 @@ 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,
"HTTPPort": self.client_http_port,
"RMRPort": self.client_rmr_port
},
"Meid": me_id,
"RANFunctionID": ran_function_id,
"RANFunctionID": rf_id,
"E2SubscriptionDirectives":{
"E2TimeoutTimerValue": 10,
"E2RetryCount": 2,
Expand All @@ -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"}
]}]
Expand Down Expand Up @@ -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



0 comments on commit a479218

Please sign in to comment.