From db933da183b51bafea606e92bb884e019c776a88 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Sep 2020 13:13:56 +0200 Subject: [PATCH 01/22] FlexRAN bugfix: first timer expiry after period --- openair2/ENB_APP/flexran_agent_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_timer.c b/openair2/ENB_APP/flexran_agent_timer.c index ffbac39983..4465c0f4c5 100644 --- a/openair2/ENB_APP/flexran_agent_timer.c +++ b/openair2/ENB_APP/flexran_agent_timer.c @@ -238,13 +238,13 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, return TIMER_SETUP_FAILED; } /* TODO check that xid does not exist? */ - t->next = sync->current + 1; + t->next = sync->current + sf; if (sync->next <= sync->current || t->next < sync->next) sync->next = t->next; sync->timer[sync->timer_num] = t; sync->timer_num++; pthread_mutex_unlock(&sync->mutex_timer); - LOG_D(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id); + LOG_I(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id); return 0; } From 7bdf807babf9ebea6b2c2f1e3453e84f4c791326 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 4 Aug 2020 19:26:33 +0200 Subject: [PATCH 02/22] FlexRAN timers: Remove destroy_timers() --- openair2/ENB_APP/flexran_agent_timer.c | 10 ---------- openair2/ENB_APP/flexran_agent_timer.h | 3 --- 2 files changed, 13 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_timer.c b/openair2/ENB_APP/flexran_agent_timer.c index 4465c0f4c5..817e93dda8 100644 --- a/openair2/ENB_APP/flexran_agent_timer.c +++ b/openair2/ENB_APP/flexran_agent_timer.c @@ -248,16 +248,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, return 0; } -err_code_t flexran_agent_destroy_timers(mid_t mod_id) { - struct timesync *sync = ×ync[mod_id]; - pthread_mutex_lock(&sync->mutex_timer); - for (int i = sync->timer_num - 1; i < 0; --i) { - flexran_agent_timer_remove_internal(sync, i); - } - pthread_mutex_unlock(&sync->mutex_timer); - return 0; -} - err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { struct timesync *sync = ×ync[mod_id]; pthread_mutex_lock(&sync->mutex_timer); diff --git a/openair2/ENB_APP/flexran_agent_timer.h b/openair2/ENB_APP/flexran_agent_timer.h index b1cf8df51f..c61f2543a3 100644 --- a/openair2/ENB_APP/flexran_agent_timer.h +++ b/openair2/ENB_APP/flexran_agent_timer.h @@ -61,9 +61,6 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, flexran_agent_timer_callback_t cb, Protocol__FlexranMessage *msg); -/* Destroy all existing timers */ -err_code_t flexran_agent_destroy_timers(mid_t mod_id); - /* Destroy the timer for task with id xid */ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid); From 33b73193e8291fbd6b1bd95df5575a4dfac85c4e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 4 Aug 2020 19:25:47 +0200 Subject: [PATCH 03/22] FlexRAN timers: enable timer add/remove within timer event A lock help during executing a timer event prevented such event from creating/removing new timers due to a dead lock. This commit changes the logic of the timing loop and adding/removing code such that this dead lock does not happen. --- openair2/ENB_APP/flexran_agent_timer.c | 43 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_timer.c b/openair2/ENB_APP/flexran_agent_timer.c index 817e93dda8..238cd344f6 100644 --- a/openair2/ENB_APP/flexran_agent_timer.c +++ b/openair2/ENB_APP/flexran_agent_timer.c @@ -58,6 +58,11 @@ struct timesync { int timer_num; flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS]; + + int add_num; + flexran_agent_timer_element_t *add_list[MAX_NUM_TIMERS]; + int remove_num; + int remove_list[MAX_NUM_TIMERS]; pthread_mutex_t mutex_timer; int exit; @@ -76,8 +81,12 @@ err_code_t flexran_agent_timer_init(mid_t mod_id) { sync->current = 0; sync->next = 0; sync->timer_num = 0; - for (int i = 0; i < MAX_NUM_TIMERS; ++i) + sync->add_num = 0; + sync->remove_num = 0; + for (int i = 0; i < MAX_NUM_TIMERS; ++i) { sync->timer[i] = NULL; + sync->add_list[i] = NULL; + } pthread_mutex_init(&sync->mutex_timer, NULL); sync->exit = 0; @@ -170,12 +179,19 @@ void *flexran_agent_timer_thread(void *args) { break; pthread_mutex_lock(&sync->mutex_timer); - sync->current++; - - if (sync->current < sync->next) { - pthread_mutex_unlock(&sync->mutex_timer); - continue; + for (int i = 0; i < sync->add_num; ++i) { + sync->timer[sync->timer_num] = sync->add_list[i]; + sync->timer_num++; } + sync->add_num = 0; + for (int i = 0; i < sync->remove_num; ++i) + flexran_agent_timer_remove_internal(sync, sync->remove_list[i]); + sync->remove_num = 0; + pthread_mutex_unlock(&sync->mutex_timer); + + sync->current++; + if (sync->current < sync->next) + continue; for (int i = 0; i < sync->timer_num; ++i) { flexran_agent_timer_element_t *t = sync->timer[i]; @@ -186,7 +202,6 @@ void *flexran_agent_timer_thread(void *args) { if (sync->next == sync->current || t->next < sync->next) sync->next = t->next; } - pthread_mutex_unlock(&sync->mutex_timer); } LOG_W(FLEXRAN_AGENT, "terminated timer thread\n"); return NULL; @@ -230,10 +245,10 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, struct timesync *sync = ×ync[mod_id]; pthread_mutex_lock(&sync->mutex_timer); - if (sync->timer_num >= MAX_NUM_TIMERS) { + if (sync->timer_num + sync->add_num >= MAX_NUM_TIMERS) { pthread_mutex_unlock(&sync->mutex_timer); LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n", - sync->timer_num, xid); + sync->timer_num + sync->add_num, xid); free(t); return TIMER_SETUP_FAILED; } @@ -241,8 +256,8 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, t->next = sync->current + sf; if (sync->next <= sync->current || t->next < sync->next) sync->next = t->next; - sync->timer[sync->timer_num] = t; - sync->timer_num++; + sync->add_list[sync->add_num] = t; + sync->add_num++; pthread_mutex_unlock(&sync->mutex_timer); LOG_I(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id); return 0; @@ -250,15 +265,15 @@ err_code_t flexran_agent_create_timer(mid_t mod_id, err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { struct timesync *sync = ×ync[mod_id]; - pthread_mutex_lock(&sync->mutex_timer); for (int i = 0; i < sync->timer_num; ++i) { if (sync->timer[i]->xid == xid) { - flexran_agent_timer_remove_internal(sync, i); + pthread_mutex_lock(&sync->mutex_timer); + sync->remove_list[sync->remove_num] = i; + sync->remove_num++; pthread_mutex_unlock(&sync->mutex_timer); return 0; } } - pthread_mutex_unlock(&sync->mutex_timer); LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid); return TIMER_ELEMENT_NOT_FOUND; } From 5d9c61ea2ac90547f69aeb27f30aa4d4db1c141c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Aug 2020 11:49:00 +0200 Subject: [PATCH 04/22] FlexRAN timers: Fix segfault timer no associated message --- openair2/ENB_APP/flexran_agent_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/ENB_APP/flexran_agent_timer.c b/openair2/ENB_APP/flexran_agent_timer.c index 238cd344f6..3a613ca8e5 100644 --- a/openair2/ENB_APP/flexran_agent_timer.c +++ b/openair2/ENB_APP/flexran_agent_timer.c @@ -282,7 +282,8 @@ err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) { void flexran_agent_timer_remove_internal(struct timesync *sync, int index) { LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n", sync->timer[index]->xid, index, sync->timer[index]->mod_id); - flexran_agent_destroy_flexran_message(sync->timer[index]->msg); + if (sync->timer[index]->msg) + flexran_agent_destroy_flexran_message(sync->timer[index]->msg); free(sync->timer[index]); for (int i = index + 1; i < sync->timer_num; ++i) sync->timer[i - 1] = sync->timer[i]; From f63cf65919cec739c48242f6f6c944ac7af98a78 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Aug 2019 19:12:22 +0200 Subject: [PATCH 05/22] FlexRAN: Improve handling of received shared objects --- openair2/ENB_APP/flexran_agent_common.c | 74 +++++++++++++++++++------ openair2/ENB_APP/flexran_agent_common.h | 1 + 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 7569ca1ac1..3002846073 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include "flexran_agent_common.h" #include "flexran_agent_common_internal.h" @@ -424,26 +427,49 @@ long timer_end(struct timespec start_time) { int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexControlDelegation *control_delegation_msg = input->control_delegation_msg; - // struct timespec vartime = timer_start(); - //Write the payload lib into a file in the cache and load the lib - char lib_name[120]; - char target[512]; - snprintf(lib_name, sizeof(lib_name), "/%s.so", control_delegation_msg->name); - strcpy(target, RC.flexran[mod_id]->cache_name); - strcat(target, lib_name); - FILE *f; - f = fopen(target, "wb"); + *msg = NULL; - if (f) { - fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f); - fclose(f); + char target[512]; + int len = snprintf(target, sizeof(target), "%s/libflex.%s.so", + RC.flexran[mod_id]->cache_name, + control_delegation_msg->name); + if (len >= sizeof(target)) { + LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file\n"); + return 0; + } + + /* use low-level API: check whether exists while creating so we can abort if + * it exists to not overwrite anything */ + int fd = open(target, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + if (fd >= 0) { + ssize_t l = write(fd, + control_delegation_msg->payload.data, + control_delegation_msg->payload.len); + close(fd); + if (l < control_delegation_msg->payload.len) { + LOG_E(FLEXRAN_AGENT, + "could not write complete control delegation to %s: only %ld out of " + "%ld bytes\n", + target, + l, + control_delegation_msg->payload.len); + return 0; + } else if (l < 0) { + LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", + target, strerror(errno)); + return 0; + } + LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target); } else { - LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n", - mod_id, target); + if (errno == EEXIST) { + LOG_I(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target); + } else { + LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", + target, strerror(errno)); + return 0; + } } - // long time_elapsed_nanos = timer_end(vartime); - *msg = NULL; return 0; } @@ -452,6 +478,22 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) { return 0; } +void *flexran_agent_load_delegated_code(mid_t mod_id, const char *name) { + char target[512]; + int len = snprintf(target, sizeof(target), "%s/libflex.%s.so", + RC.flexran[mod_id]->cache_name, name); + if (len >= sizeof(target)) { + LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot read object\n"); + return 0; + } + + LOG_I(FLEXRAN_AGENT, "Opening pushed code: %s\n", target); + void *lib = dlopen(target, RTLD_NOW); + if (lib == NULL) + LOG_E(FLEXRAN_AGENT, "Could not load library: %s\n", dlerror()); + return lib; +} + int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg; diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index fe7b49107c..91c8a95e44 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -131,6 +131,7 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg); /* Control delegation message constructor and destructor */ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg); +void *flexran_agent_load_delegated_code(mid_t mod_id, const char *name); /* Policy reconfiguration message constructor and destructor */ int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); From 61344db9dd724d68deb9be2d7849c8f0aba8ffcf Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 29 Aug 2019 14:32:13 +0200 Subject: [PATCH 06/22] FlexRAN delegation: mapper function to return path name --- openair2/ENB_APP/flexran_agent_common.c | 24 +++++++++++++----------- openair2/ENB_APP/flexran_agent_common.h | 7 ++++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 3002846073..54335728e2 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -478,20 +478,22 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) { return 0; } -void *flexran_agent_load_delegated_code(mid_t mod_id, const char *name) { - char target[512]; - int len = snprintf(target, sizeof(target), "%s/libflex.%s.so", +int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name, + char *path, int maxlen) { + int len = snprintf(path, maxlen, "%s/libflex.%s.so", RC.flexran[mod_id]->cache_name, name); - if (len >= sizeof(target)) { - LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot read object\n"); - return 0; + if (len >= maxlen) { + LOG_E(FLEXRAN_AGENT, "path has been truncated, cannot read object\n"); + return -1; } - LOG_I(FLEXRAN_AGENT, "Opening pushed code: %s\n", target); - void *lib = dlopen(target, RTLD_NOW); - if (lib == NULL) - LOG_E(FLEXRAN_AGENT, "Could not load library: %s\n", dlerror()); - return lib; + struct stat buf; + int status = stat(path, &buf); + if (status < 0) { + LOG_E(FLEXRAN_AGENT, "Could not stat object %s: %s\n", path, strerror(errno)); + return -1; + } + return 0; } int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index 91c8a95e44..d85e127dbc 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -131,7 +131,12 @@ int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg); /* Control delegation message constructor and destructor */ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg); -void *flexran_agent_load_delegated_code(mid_t mod_id, const char *name); +/* Map a name from a control_delegation message to a file name. The function + * stat()s the file to check existence and returns the complete path name in + * path. The length in path needs to be maxlen, the maximum length the path may + * have. */ +int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name, + char *path, int maxlen); /* Policy reconfiguration message constructor and destructor */ int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); From 1c5a4eb645cb903e77a4d85c946e25b4881fbd4f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 10 Aug 2020 18:25:28 +0200 Subject: [PATCH 07/22] FlexRAN: add control app delegation type in protobuf --- openair2/ENB_APP/MESSAGES/V2/control_delegation.proto | 1 + openair2/ENB_APP/MESSAGES/V2/flexran.proto | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto index ef0eea3bd2..7e5d0ac7a3 100644 --- a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto +++ b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto @@ -3,4 +3,5 @@ package protocol; enum flex_control_delegation_type { FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation + FLCDT_AGENT_CONTROL_APP = 2; // Generic control application } diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 3b47ff263b..0b77ab5d5a 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -225,7 +225,7 @@ message flex_ue_state_change { message flex_control_delegation { optional flex_header header = 1; - optional uint32 delegation_type = 2; // Bitmap of FLCDT_* flags + optional flex_control_delegation_type delegation_type = 2; // The delegated object type, decides about further processing optional bytes payload = 3; // Byte array of shared lib containing the delegated functions optional string name = 4; // The delegated functions names ordered based on bitmap flags } From 6e2c8d847a06a7a383d42bd783188711e40aa7f1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 21 Aug 2020 08:49:32 +0200 Subject: [PATCH 08/22] FlexRAN: new agent reconfiguration syntax, instead of YAML --- .../MESSAGES/V2/control_delegation.proto | 20 +++++++++++++++++++ openair2/ENB_APP/MESSAGES/V2/flexran.proto | 1 + 2 files changed, 21 insertions(+) diff --git a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto index 7e5d0ac7a3..a646a978a9 100644 --- a/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto +++ b/openair2/ENB_APP/MESSAGES/V2/control_delegation.proto @@ -5,3 +5,23 @@ enum flex_control_delegation_type { FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation FLCDT_AGENT_CONTROL_APP = 2; // Generic control application } + +message flex_agent_reconfiguration_system { + optional string system = 1; + repeated flex_agent_reconfiguration_subsystem subsystems = 2; +} + +message flex_agent_reconfiguration_subsystem { + optional string name = 1; // Name of the object (app name or user plane object) + optional string behavior = 2; // For an app: a callback in a shared library. For any other subsystem: an object name (shared library) with defined syntax. + map params = 3; // Param configurations depending on callback/shared library above. +} + +message flex_agent_reconfiguration_param { + oneof param { + int32 integer = 1; + float floating = 2; + bool boolean = 3; + string str = 4; + } +} diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 0b77ab5d5a..411f0196cb 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -237,6 +237,7 @@ message flex_control_delegation { message flex_agent_reconfiguration { optional flex_header header = 1; optional string policy = 2; // The policy changes using YAML syntax in string format + repeated flex_agent_reconfiguration_system systems = 3; // The policy changes. } // Extensions of the echo request and reply From 9e4320864f389da1340a291067fcf4a85ec4c9c9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 21 Aug 2020 10:08:24 +0200 Subject: [PATCH 09/22] FlexRAN control delegation: write/remove depending if payload present --- openair2/ENB_APP/flexran_agent_common.c | 65 ++++++++++++++----------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 54335728e2..23809d882e 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -434,40 +434,47 @@ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol_ RC.flexran[mod_id]->cache_name, control_delegation_msg->name); if (len >= sizeof(target)) { - LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file\n"); + LOG_E(FLEXRAN_AGENT, "target has been truncated, cannot write file name\n"); return 0; } - /* use low-level API: check whether exists while creating so we can abort if - * it exists to not overwrite anything */ - int fd = open(target, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); - if (fd >= 0) { - ssize_t l = write(fd, - control_delegation_msg->payload.data, - control_delegation_msg->payload.len); - close(fd); - if (l < control_delegation_msg->payload.len) { - LOG_E(FLEXRAN_AGENT, - "could not write complete control delegation to %s: only %ld out of " - "%ld bytes\n", - target, - l, - control_delegation_msg->payload.len); - return 0; - } else if (l < 0) { - LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", - target, strerror(errno)); - return 0; - } - LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target); - } else { - if (errno == EEXIST) { - LOG_I(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target); + if (control_delegation_msg->has_payload) { + /* use low-level API: check whether exists while creating so we can abort if + * it exists to not overwrite anything */ + int fd = open(target, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + if (fd >= 0) { + ssize_t l = write(fd, + control_delegation_msg->payload.data, + control_delegation_msg->payload.len); + close(fd); + if (l < control_delegation_msg->payload.len) { + LOG_E(FLEXRAN_AGENT, + "could not write complete control delegation to %s: only %ld out of " + "%ld bytes\n", + target, + l, + control_delegation_msg->payload.len); + return 0; + } else if (l < 0) { + LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", + target, strerror(errno)); + return 0; + } + LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target); } else { - LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", - target, strerror(errno)); - return 0; + if (errno == EEXIST) { + LOG_I(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target); + } else { + LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", + target, strerror(errno)); + return 0; + } } + } else { + LOG_W(FLEXRAN_AGENT, "remove file %s\n", target); + int rc = remove(target); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", target, strerror(errno)); } return 0; From 8772856fd40195f0706d5840469cb2af6cf40a91 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 11 Aug 2020 14:31:20 +0200 Subject: [PATCH 10/22] FlexRAN: Add app loader/CM --- cmake_targets/CMakeLists.txt | 1 + openair2/ENB_APP/flexran_agent.c | 3 + openair2/ENB_APP/flexran_agent.h | 1 + openair2/ENB_APP/flexran_agent_app.c | 190 +++++++++++++++++++++++ openair2/ENB_APP/flexran_agent_app.h | 70 +++++++++ openair2/ENB_APP/flexran_agent_common.c | 1 + openair2/ENB_APP/flexran_agent_handler.c | 1 + 7 files changed, 267 insertions(+) create mode 100644 openair2/ENB_APP/flexran_agent_app.c create mode 100644 openair2/ENB_APP/flexran_agent_app.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 1be71691c4..21d361be09 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1095,6 +1095,7 @@ add_library(FLEXRAN_AGENT ${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c + ${OPENAIR2_DIR}/ENB_APP/flexran_agent_app.c ) add_dependencies(FLEXRAN_AGENT rrc_flag) set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT) diff --git a/openair2/ENB_APP/flexran_agent.c b/openair2/ENB_APP/flexran_agent.c index 519d2bef4b..78e5ce8dde 100644 --- a/openair2/ENB_APP/flexran_agent.c +++ b/openair2/ENB_APP/flexran_agent.c @@ -233,6 +233,9 @@ int flexran_agent_start(mid_t mod_id) agent_task_created = 1; } + /* Init the app sublayer */ + flexran_agent_app_init(mod_id); + pthread_mutex_init(&flexran->mutex_node_ctrl, NULL); pthread_cond_init(&flexran->cond_node_ctrl, NULL); diff --git a/openair2/ENB_APP/flexran_agent.h b/openair2/ENB_APP/flexran_agent.h index 42295fc111..43e7d7210a 100644 --- a/openair2/ENB_APP/flexran_agent.h +++ b/openair2/ENB_APP/flexran_agent.h @@ -41,6 +41,7 @@ #include "flexran_agent_rrc.h" #include "flexran_agent_pdcp.h" #include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" #include "common/utils/LOG/log.h" #include "assertions.h" diff --git a/openair2/ENB_APP/flexran_agent_app.c b/openair2/ENB_APP/flexran_agent_app.c new file mode 100644 index 0000000000..fd6a51c97e --- /dev/null +++ b/openair2/ENB_APP/flexran_agent_app.c @@ -0,0 +1,190 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file flexran_agent_app.c + * \brief CM for handling of applications + * \author Robert Schmidt + * \date 2020 + * \version 0.1 + */ + +#include "flexran_agent_app.h" +#include "queue.h" +#include + +/* app definition */ +typedef struct flexran_agent_app_internal_s { + char *name; + void *dl_handle; + flexran_agent_app_t *app; + + SLIST_ENTRY (flexran_agent_app_internal_s) entries; +} flexran_agent_app_internal_t; + +/* a list of all apps */ +SLIST_HEAD(flexran_apps_s, flexran_agent_app_internal_s) flexran_apps[NUM_MAX_ENB]; + +void flexran_agent_app_init(mid_t mod_id) { + //flexran_apps[mod_id] = SLIST_HEAD_INITIALIZER(flexran_apps[mod_id]); + SLIST_INIT(&flexran_apps[mod_id]); +} + +int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name) { + app->start(mod_id, NULL, 0); + + flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t)); + DevAssert(so); + so->name = strdup(name); + DevAssert(so->name); + so->dl_handle = NULL; + so->app = app; + SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries); + return 0; +} + +int flexran_agent_start_app(mid_t mod_id, Protocol__FlexAgentReconfigurationSubsystem *sub) { + char s[512]; + int rc = flexran_agent_map_name_to_delegated_object(mod_id, sub->name, s, 512); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", sub->name); + return -1; + } + void *h = dlopen(s, RTLD_NOW); + if (!h) { + LOG_E(FLEXRAN_AGENT, "cannot open shared object %s\n", s); + return -1; + } + flexran_agent_app_t *app = dlsym(h, "app"); + if (!app) { + LOG_E(FLEXRAN_AGENT, "cannot locate app inside of shared object %s\n", s); + return -1; + } + app->start(mod_id, sub->params, sub->n_params); + + flexran_agent_app_internal_t *so = malloc(sizeof(flexran_agent_app_internal_t)); + DevAssert(so); + so->name = strdup(sub->name); + DevAssert(so->name); + so->dl_handle = h; + so->app = app; + SLIST_INSERT_HEAD(&flexran_apps[mod_id], so, entries); + + return 0; +} + +int flexran_agent_stop_app(mid_t mod_id, char *name) { + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) { + if (strcmp(so->name, name) == 0) { + LOG_I(FLEXRAN_AGENT, "application %s seems to be running\n", name); + break; + } + } + if (!so) { + LOG_E(FLEXRAN_AGENT, "no such application %s found\n", name); + return -1; + } + flexran_agent_app_t *app = so->app; + app->stop(mod_id); + + SLIST_REMOVE(&flexran_apps[mod_id], so, flexran_agent_app_internal_s, entries); + free(so->name); + if (so->dl_handle) + dlclose(so->dl_handle); + free(so); + so = NULL; + return 0; +} + +int flexran_agent_reconfig_app( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem *sub) +{ + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) { + if (strcmp(so->name, sub->name) == 0) { + LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name); + break; + } + } + if (!so) { + LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name); + return -1; + } + flexran_agent_app_t *app = so->app; + LOG_I(FLEXRAN_AGENT, "reconfiguring app %s\n", so->name); + app->reconfig(mod_id, sub->params, sub->n_params); + return 0; +} + +int flexran_agent_custom_command_app( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem *sub) +{ + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) { + if (strcmp(so->name, sub->name) == 0) { + LOG_I(FLEXRAN_AGENT, "application %s is running\n", sub->name); + break; + } + } + if (!so) { + LOG_E(FLEXRAN_AGENT, "no such application %s found\n", sub->name); + return -1; + } + void (*cmd)(mid_t, Protocol__FlexAgentReconfigurationSubsystem *) = dlsym(so->dl_handle, sub->behavior); + if (!cmd) { + LOG_E(FLEXRAN_AGENT, + "cannot locate command %s inside of app %s\n", + sub->behavior, + so->name); + return -1; + } + + LOG_I(FLEXRAN_AGENT, + "calling command %s inside of app %s\n", + sub->behavior, + so->name); + (*cmd)(mod_id, sub); + return 0; +} + +void flexran_agent_handle_apps( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem **subs, + int n_subs) { + for (int i = 0; i < n_subs; ++i) { + Protocol__FlexAgentReconfigurationSubsystem *s = subs[i]; + if (strcmp(s->behavior, "start") == 0) { + int rc = flexran_agent_start_app(mod_id, s); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "application \"%s\" started\n", s->name); + } else if (strcmp(s->behavior, "stop") == 0) { + int rc = flexran_agent_stop_app(mod_id, s->name); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "application \"%s\" stopped\n", s->name); + } else if (strcmp(s->behavior, "reconfig") == 0) { + flexran_agent_reconfig_app(mod_id, s); + } else { + flexran_agent_custom_command_app(mod_id, s); + } + } +} diff --git a/openair2/ENB_APP/flexran_agent_app.h b/openair2/ENB_APP/flexran_agent_app.h new file mode 100644 index 0000000000..f5e1fe54c3 --- /dev/null +++ b/openair2/ENB_APP/flexran_agent_app.h @@ -0,0 +1,70 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file flexran_agent_app.h + * \brief Common app definitions + * \author Robert Schmidt + * \date 2020 + * \version 0.1 + */ + +#ifndef BURST_ANALYSIS_LL_H_ +#define BURST_ANALYSIS_LL_H_ + +#include "flexran_agent_common.h" +#include "flexran_agent_async.h" +#include "flexran_agent_extern.h" +#include "flexran_agent_timer.h" +#include "flexran_agent_defs.h" +#include "flexran_agent_net_comm.h" +#include "flexran_agent_ran_api.h" +#include "flexran_agent_phy.h" +#include "flexran_agent_mac.h" +#include "flexran_agent_rrc.h" +#include "flexran_agent_pdcp.h" +#include "flexran_agent_s1ap.h" +#include "common/utils/LOG/log.h" +#include "assertions.h" + +/* App type: to be implemented by shared libraries */ +typedef struct { + int (*start)(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p); + int (*reconfig)(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p); + int (* stop)(mid_t mod_id); +} flexran_agent_app_t; + +/* FlexRAN agent app handling init */ +void flexran_agent_app_init(mid_t mod_id); + +/* Start an app from within the agent */ +int flexran_agent_start_app_direct(mid_t mod_id, flexran_agent_app_t *app, char *name); + +/* FlexRAN agent handler to setup/teardown apps */ +void flexran_agent_handle_apps( + mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem **subs, + int n_subs); + +#endif diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 23809d882e..7a7b4febd9 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -42,6 +42,7 @@ #include "flexran_agent_mac.h" #include "flexran_agent_rrc.h" #include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" //#include "PHY/extern.h" #include "common/utils/LOG/log.h" #include "flexran_agent_mac_internal.h" diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index d991078cf7..654f89d876 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -32,6 +32,7 @@ #include "flexran_agent_rrc.h" #include "flexran_agent_pdcp.h" #include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" #include "flexran_agent_timer.h" #include "flexran_agent_ran_api.h" #include "common/utils/LOG/log.h" From fde312782346d2a7207baa120a843274c76b9e39 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 21 Aug 2020 10:11:20 +0200 Subject: [PATCH 11/22] FlexRAN Agent reconfiguration: call flexran_agent_handle_apps() --- openair2/ENB_APP/flexran_agent_common.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 7a7b4febd9..2df188635b 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -507,7 +507,23 @@ int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name, int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexAgentReconfiguration *agent_reconfiguration_msg = input->agent_reconfiguration_msg; - apply_reconfiguration_policy(mod_id, agent_reconfiguration_msg->policy, strlen(agent_reconfiguration_msg->policy)); + if (agent_reconfiguration_msg->policy) { + /* for compatibility: call old YAML configuration code, although we don't + * use it anymore */ + apply_reconfiguration_policy(mod_id, + agent_reconfiguration_msg->policy, + strlen(agent_reconfiguration_msg->policy)); + } + for (int i = 0; i < agent_reconfiguration_msg->n_systems; ++i) { + const Protocol__FlexAgentReconfigurationSystem *sys = agent_reconfiguration_msg->systems[i]; + if (strcmp(sys->system, "app") == 0) { + flexran_agent_handle_apps(mod_id, sys->subsystems, sys->n_subsystems); + } else { + LOG_E(FLEXRAN_AGENT, + "unknown system name %s in flex_agent_reconfiguration message\n", + sys->system); + } + } *msg = NULL; return 0; } From 865348b0471d71f4bfcd669fff4619794118a635 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 12 Aug 2020 08:25:12 +0200 Subject: [PATCH 12/22] FlexRAN agent app: Add sample FlexRAN app --- cmake_targets/CMakeLists.txt | 7 ++ openair2/ENB_APP/flexran_apps/sample.c | 121 +++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 openair2/ENB_APP/flexran_apps/sample.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 21d361be09..f213c7380d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1099,6 +1099,13 @@ add_library(FLEXRAN_AGENT ) add_dependencies(FLEXRAN_AGENT rrc_flag) set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT) +add_library(flapp_sample SHARED + ${OPENAIR2_DIR}/ENB_APP/flexran_apps/sample.c +) +set_target_properties(flapp_sample PROPERTIES C_VISIBILITY_PRESET hidden) +add_custom_target(flapp_all DEPENDS + flapp_sample +) #include_directories(${OPENAIR2_DIR}/ENB_APP) set(PROTOBUF_LIB "protobuf-c") diff --git a/openair2/ENB_APP/flexran_apps/sample.c b/openair2/ENB_APP/flexran_apps/sample.c new file mode 100644 index 0000000000..65be2a43df --- /dev/null +++ b/openair2/ENB_APP/flexran_apps/sample.c @@ -0,0 +1,121 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file sample.c + * \brief flexran sample app + * \author Robert Schmidt + * \date 2020 + * \version 0.1 + */ + +#include "flexran_agent_common.h" +#include "flexran_agent_async.h" +#include "flexran_agent_extern.h" +#include "flexran_agent_timer.h" +#include "flexran_agent_defs.h" +#include "flexran_agent_net_comm.h" +#include "flexran_agent_ran_api.h" +#include "flexran_agent_phy.h" +#include "flexran_agent_mac.h" +#include "flexran_agent_rrc.h" +#include "flexran_agent_pdcp.h" +#include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" +#include "common/utils/LOG/log.h" +#include "assertions.h" + +/* callback to be called for event: shows exemplary variable use and use of RAN + * API */ +int tick; +Protocol__FlexranMessage *sample_tick( + mid_t mod_id, + const Protocol__FlexranMessage *msg) { + tick++; + const int num = flexran_get_mac_num_ues(mod_id); + LOG_I(FLEXRAN_AGENT, "%s(): tick %d number UEs %d\n", __func__, tick, num); + return NULL; +} + +void print_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { + LOG_I(FLEXRAN_AGENT, "%s(): received %d parameters\n", __func__, n_p); + for (int i = 0; i < n_p; ++i) { + switch (p[i]->value->param_case) { + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET: + LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER: + LOG_I(FLEXRAN_AGENT, " param %s is %d\n", p[i]->key, p[i]->value->integer); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_FLOATING: + LOG_I(FLEXRAN_AGENT, " param %s is %f\n", p[i]->key, p[i]->value->floating); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_BOOLEAN: + LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->boolean ? "true" : "false"); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR: + LOG_I(FLEXRAN_AGENT, " param %s is %s\n", p[i]->key, p[i]->value->str); + break; + default: + LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key); + break; + }; + } +} + +/* sa_start: entry point for sample app. Installs a callback using the timer + * API to have function sample_tick() called every 5s */ +#define TIMER 22 +int sa_start(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) { + LOG_W(FLEXRAN_AGENT, "%s(): enable sample app timer\n", __func__); + flexran_agent_create_timer(mod_id, + 5000, + FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, + TIMER, + sample_tick, + NULL); + print_param(p, n_p); + return 0; +} + +int sa_reconfig(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) +{ + print_param(p, n_p); + return 0; +} + +/* stop function: cleans up before app can be unloaded. Here: stop the timer */ +int sa_stop(mid_t mod_id) { + LOG_W(FLEXRAN_AGENT, "%s(): disable sample app timer\n", __func__); + flexran_agent_destroy_timer(mod_id, TIMER); + return 0; +} + +/* app definition. visibility should be set to default so this symbol is + * reachable from outside */ +flexran_agent_app_t __attribute__ ((visibility ("default"))) app = { + .start = sa_start, + .reconfig = sa_reconfig, + .stop = sa_stop +}; From c500babe8b4e9a1d7079f463ba5cdbda01186b98 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Sep 2020 14:01:13 +0200 Subject: [PATCH 13/22] FlexRAN fixup: FLPT_DELEGATE_REQUEST and corresp. destroy() --- openair2/ENB_APP/MESSAGES/V2/header.proto | 1 + openair2/ENB_APP/flexran_agent_common.c | 9 +++++++++ openair2/ENB_APP/flexran_agent_common.h | 3 +++ openair2/ENB_APP/flexran_agent_handler.c | 5 +++++ 4 files changed, 18 insertions(+) diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto index 41b2b37f7a..5e224f64f7 100644 --- a/openair2/ENB_APP/MESSAGES/V2/header.proto +++ b/openair2/ENB_APP/MESSAGES/V2/header.proto @@ -44,5 +44,6 @@ enum flex_type { FLPT_RECONFIGURE_AGENT = 16; FLPT_RRC_TRIGGERING = 17; FLPT_UL_MAC_CONFIG = 18; + FLPT_DELEGATE_REQUEST = 22; } diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 2df188635b..e1df8a543e 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -533,6 +533,15 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg) { return 0; } +int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg) { + if(msg->msg_case != PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG) + return -1; + + free(msg->control_del_req_msg->header); + free(msg->control_del_req_msg->name); + free(msg); + return 0; +} int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { xid_t xid; diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index d85e127dbc..ae690c7124 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -142,6 +142,9 @@ int flexran_agent_map_name_to_delegated_object(mid_t mod_id, const char *name, int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); +/* Policy reconfiguration request message destructor */ +int flexran_agent_destroy_control_delegation_request(Protocol__FlexranMessage *msg); + /* rrc triggering measurement message constructor and destructor */ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg); diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 654f89d876..addcd6a142 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -81,6 +81,11 @@ flexran_agent_message_destruction_callback message_destruction_callback[] = { flexran_agent_destroy_ue_state_change, flexran_agent_destroy_control_delegation, flexran_agent_destroy_agent_reconfiguration, + NULL, /* flex_rrc_triggering */ + NULL, /* flex_ul_mac_config */ + NULL, /* flex_disconnect */ + NULL, /* flex_ho_command */ + flexran_agent_destroy_control_delegation_request, }; /* static const char *flexran_agent_direction2String[] = { */ From 9de83a047a5baf6948a468664c841018c41b8be2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 28 Jul 2020 17:02:49 +0200 Subject: [PATCH 14/22] FlexRAN: Add control_delegation_request protobuf message --- openair2/ENB_APP/MESSAGES/V2/flexran.proto | 8 ++++++++ openair2/ENB_APP/flexran_agent_common.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 411f0196cb..7fd19c805c 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -7,6 +7,7 @@ import "time_common.proto"; import "config_messages.proto"; import "controller_commands.proto"; import "config_common.proto"; +import "control_delegation.proto"; message flexran_message { optional flexran_direction msg_dir = 100; @@ -32,6 +33,7 @@ message flexran_message { flex_ul_mac_config ul_mac_config_msg = 19; flex_disconnect disconnect_msg = 20; flex_ho_command ho_command_msg = 21; + flex_control_delegation_request control_del_req_msg = 22; } } @@ -230,6 +232,12 @@ message flex_control_delegation { optional string name = 4; // The delegated functions names ordered based on bitmap flags } +message flex_control_delegation_request { + optional flex_header header = 1; + optional flex_control_delegation_type delegation_type = 2; + optional string name = 4; +} + // // Agent reconfiguration message // diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index e1df8a543e..fa505c5415 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -464,12 +464,12 @@ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol_ LOG_I(FLEXRAN_AGENT, "wrote shared object %s\n", target); } else { if (errno == EEXIST) { - LOG_I(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target); + LOG_W(FLEXRAN_AGENT, "file %s already exists, remove it first\n", target); } else { LOG_E(FLEXRAN_AGENT, "can not write control delegation data to %s: %s\n", target, strerror(errno)); - return 0; } + return 0; } } else { LOG_W(FLEXRAN_AGENT, "remove file %s\n", target); From 0f641b7d9cb4537f4b0c8e40687130da2af8c7ba Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Sep 2020 09:20:44 +0200 Subject: [PATCH 15/22] If unknown scheduler, save message and contact controller --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index f1daacbb65..03f776a87d 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -40,6 +40,8 @@ #include "common/utils/LOG/log.h" +#include + /*Array containing the Agent-MAC interfaces*/ AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]; @@ -53,6 +55,13 @@ struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB]; +/* Ringbuffer related to slice configuration if we need to wait for additional + * controller information */ +struct lfds700_ringbuffer_element *store_slice_config_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state store_slice_config_ringbuffer_state[NUM_MAX_ENB]; +/* stores the (increasing) xid for messages to prevent double use */ +int xid = 50; + /* Ringbuffer-related to slice configuration */ struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; @@ -1363,6 +1372,19 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { &scrng, NULL); + struct lfds700_misc_prng_state sscrng; + i = posix_memalign((void **) &store_slice_config_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &store_slice_config_ringbuffer_state[mod_id], + store_slice_config_array[mod_id], + num_elements, + &sscrng, + NULL); + struct lfds700_misc_prng_state uarng; i = posix_memalign((void **) &ue_assoc_array[mod_id], LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, @@ -1659,6 +1681,8 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) free(dl_mac_config_array[mod_id]); lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL ); free(slice_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&store_slice_config_ringbuffer_state[mod_id], NULL ); + free(store_slice_config_array[mod_id]); lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL ); free(ue_assoc_array[mod_id]); lfds700_misc_library_cleanup(); @@ -1698,6 +1722,69 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { flexran_agent_destroy_mac_slice_config(&helper); } +int check_scheduler(mid_t mod_id, char *s) { + return dlsym(NULL, s) != NULL; +} + +void request_scheduler(mid_t mod_id, char *s, int xid) { + LOG_W(FLEXRAN_AGENT, + "unknown scheduler %s, requesting controller to send it\n", + s); + Protocol__FlexControlDelegationRequest *req = malloc(sizeof(Protocol__FlexControlDelegationRequest)); + DevAssert(req); + protocol__flex_control_delegation_request__init(req); + Protocol__FlexHeader *header = NULL; + int rc = flexran_create_header( + xid, PROTOCOL__FLEX_TYPE__FLPT_DELEGATE_REQUEST, &header); + AssertFatal(rc == 0, "%s(): cannot create header\n", __func__); + req->header = header; + req->delegation_type = PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER; + req->name = strdup(s); + + Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage)); + DevAssert(msg); + protocol__flexran_message__init(msg); + msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DEL_REQ_MSG; + msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; + msg->control_del_req_msg = req; + + int size = 0; + void *data = flexran_agent_pack_message(msg, &size); + if (flexran_agent_msg_send(mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0) + LOG_E(FLEXRAN_AGENT, "%s(): error while sending message\n", __func__); +} + +Protocol__FlexranMessage *request_scheduler_timeout( + mid_t mod_id, + const Protocol__FlexranMessage *msg) { + const Protocol__FlexEnbConfigReply *ecr = msg->enb_config_reply_msg; + + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + + Protocol__FlexranMessage *smsg = NULL; + struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &smsg, &ls)) { + AssertFatal(msg == smsg, + "expected and returned enb_config_reply are not the same\n"); + AssertFatal(ecr->header->xid == smsg->enb_config_reply_msg->header->xid, + "expected and returned enb_config_reply are not the same\n"); + } else { + LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__); + } + /* call the helper so that scheduler names are correctly freed */ + helper_destroy_mac_slice_config(ecr->cell_config[0]->slice_config); + ecr->cell_config[0]->slice_config = NULL; + /* we should not call flexran_agent_destroy_enb_config_reply(smsg); since + * upon timer removal, this is automatically done */ + LOG_W(FLEXRAN_AGENT, + "remove stored slice config (xid %d) after timeout\n", + ecr->header->xid); + flexran_agent_destroy_timer(mod_id, ecr->header->xid); + return NULL; +} + void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { if (!*slice_config) return; /* just use the memory and set to NULL in original */ @@ -1709,6 +1796,61 @@ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice lfds700_misc_prng_init(&ls); enum lfds700_misc_flag overwrite_occurred_flag; + int put_on_hold = 0; + if (sc->dl->scheduler && !check_scheduler(mod_id, sc->dl->scheduler)) { + request_scheduler(mod_id, sc->dl->scheduler, xid++); + put_on_hold = 1; + } + for (int i = 0; i < sc->dl->n_slices; ++i) { + Protocol__FlexSlice *sl = sc->dl->slices[i]; + if (sl->scheduler && !check_scheduler(mod_id, sl->scheduler)) { + request_scheduler(mod_id, sl->scheduler, xid++); + put_on_hold = 1; + } + } + if (put_on_hold) { + Protocol__FlexEnbConfigReply *reply = malloc(sizeof(Protocol__FlexEnbConfigReply)); + DevAssert(reply); + protocol__flex_enb_config_reply__init(reply); + /* use the last used xid so we can correlate answer and waiting config */ + int rc = flexran_create_header( + xid - 1, PROTOCOL__FLEX_TYPE__FLPT_GET_ENB_CONFIG_REPLY, &reply->header); + AssertFatal(rc == 0, "%s(): cannot create header\n", __func__); + reply->n_cell_config = 1; + reply->cell_config = malloc(sizeof(Protocol__FlexCellConfig *)); + DevAssert(reply->cell_config); + reply->cell_config[0] = malloc(sizeof(Protocol__FlexCellConfig)); + DevAssert(reply->cell_config[0]); + protocol__flex_cell_config__init(reply->cell_config[0]); + reply->cell_config[0]->slice_config = sc; + + Protocol__FlexranMessage *msg = malloc(sizeof(Protocol__FlexranMessage)); + DevAssert(msg); + protocol__flexran_message__init(msg); + msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG; + msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__INITIATING_MESSAGE; + msg->enb_config_reply_msg = reply; + + Protocol__FlexEnbConfigReply *o; + lfds700_ringbuffer_write(&store_slice_config_ringbuffer_state[mod_id], + NULL, + (void *)msg, + &overwrite_occurred_flag, + NULL, + (void **) &o, + &ls); + AssertFatal(overwrite_occurred_flag == LFDS700_MISC_FLAG_LOWERED, + "unhandled: stored slice config for controller has been overwritten\n"); + + flexran_agent_create_timer(mod_id, + 3000, + FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, + xid - 1, + request_scheduler_timeout, + msg); /* need reply for xid */ + return; + } + Protocol__FlexSliceConfig *overwritten_sc; lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id], NULL, From 65e52fcf11e867b78d8bf923d6eb4a62d1b8b0b3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 9 Sep 2020 15:52:19 +0200 Subject: [PATCH 16/22] Inform MAC of control delegation and load in user plane --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 78 ++++++++++++++++++- .../CONTROL_MODULES/MAC/flexran_agent_mac.h | 8 +- openair2/ENB_APP/flexran_agent_common.c | 13 +++- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 03f776a87d..3396c05b70 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1785,7 +1785,9 @@ Protocol__FlexranMessage *request_scheduler_timeout( return NULL; } -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { +void prepare_update_slice_config(mid_t mod_id, + Protocol__FlexSliceConfig **slice_config, + int request_objects) { if (!*slice_config) return; /* just use the memory and set to NULL in original */ Protocol__FlexSliceConfig *sc = *slice_config; @@ -1797,11 +1799,13 @@ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice enum lfds700_misc_flag overwrite_occurred_flag; int put_on_hold = 0; - if (sc->dl->scheduler && !check_scheduler(mod_id, sc->dl->scheduler)) { + if (request_objects + && sc->dl->scheduler + && !check_scheduler(mod_id, sc->dl->scheduler)) { request_scheduler(mod_id, sc->dl->scheduler, xid++); put_on_hold = 1; } - for (int i = 0; i < sc->dl->n_slices; ++i) { + for (int i = 0; request_objects && i < sc->dl->n_slices; ++i) { Protocol__FlexSlice *sl = sc->dl->slices[i]; if (sl->scheduler && !check_scheduler(mod_id, sl->scheduler)) { request_scheduler(mod_id, sl->scheduler, xid++); @@ -1907,3 +1911,71 @@ void flexran_agent_slice_update(mid_t mod_id) { free(ue_config); } } + +void flexran_agent_mac_inform_delegation(mid_t mod_id, + Protocol__FlexControlDelegation *cdm) { + LOG_W(FLEXRAN_AGENT, + "received FlexControlDelegation message for object '%s' xid %d\n", + cdm->name, + cdm->header->xid); + if (cdm->header->xid < xid - 1) { + LOG_I(FLEXRAN_AGENT, + "waiting for %d more messages (up to xid %d)\n", + xid - 1 - cdm->header->xid, + xid - 1); + return; + } + /* should receive up to xid - 1, otherwise it means there was no request */ + AssertFatal(xid > cdm->header->xid, + "received control delegation with xid %d that we never requested " + "(last request %d)\n", + cdm->header->xid, + xid - 1); + + /* Load the library so the user plane can search it */ + char s[512]; + int rc = flexran_agent_map_name_to_delegated_object(mod_id, cdm->name, s, 512); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", cdm->name); + return; + } + /* TODO where to unload/save handle?? */ + void *h = dlopen(s, RTLD_NOW); + if (!h) { + LOG_E(FLEXRAN_AGENT, "dlopen(): %s\n", dlerror()); + return; + } + LOG_I(FLEXRAN_AGENT, "library handle %p\n", h); + + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + + Protocol__FlexranMessage *msg = NULL; + struct lfds700_ringbuffer_state *state = &store_slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &msg, &ls) == 0) { + LOG_E(FLEXRAN_AGENT, "%s(): could not read config from ringbuffer\n", __func__); + return; + } + AssertFatal(cdm->header->xid == msg->enb_config_reply_msg->header->xid, + "expected and retrieved xid of stored slice configuration does " + "not match (expected %d, retrieved %d)\n", + cdm->header->xid, + msg->enb_config_reply_msg->header->xid); + + /* Since we recover, stop the timeout */ + rc = flexran_agent_destroy_timer(mod_id, cdm->header->xid); + + prepare_update_slice_config( + mod_id, + &msg->enb_config_reply_msg->cell_config[0]->slice_config, + 0 /* don't do a request */); + /* we should not call flexran_agent_destroy_enb_config_reply(smsg); since + * upon timer removal, this is automatically done. + * prepare_update_slice_config() takes ownership of the slice config, it is + * freed inside */ + + + /* TODO save dlhandle in list with name. If it has been installed and nothing + * references it after a reconfiguration, free and remove */ +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 5a8d4f31aa..7eade10c03 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -117,7 +117,9 @@ void flexran_agent_slice_update(mid_t mod_id); /* marks slice_config so that it can be applied later. Takes ownership of the * FlexSliceConfig message */ -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice); +void prepare_update_slice_config(mid_t mod_id, + Protocol__FlexSliceConfig **slice, + int request_objects); /* inserts a new ue_config into the structure keeping ue to slice association * updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */ @@ -127,4 +129,8 @@ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_con * flexran_agent_fill_mac_cell_config() */ void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); +/* information about a new (potentially relevant) control delegation message */ +void flexran_agent_mac_inform_delegation(mid_t mod_id, + Protocol__FlexControlDelegation *cdm); + #endif diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index fa505c5415..345cb5ad96 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -478,6 +478,15 @@ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol_ LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", target, strerror(errno)); } + if (control_delegation_msg->has_delegation_type + && control_delegation_msg->delegation_type == PROTOCOL__FLEX_CONTROL_DELEGATION_TYPE__FLCDT_MAC_DL_UE_SCHEDULER + && control_delegation_msg->header + && control_delegation_msg->header->has_xid) { + /* Inform the MAC subsystem that a control delegation for it has arrived */ + /* TODO this should be triggered by an agent reconfiguration? */ + flexran_agent_mac_inform_delegation(mod_id, control_delegation_msg); + } + return 0; } @@ -957,7 +966,9 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot if (enb_config->n_cell_config > 0) { if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config); + prepare_update_slice_config(mod_id, + &enb_config->cell_config[0]->slice_config, + 1 /* request objects if necessary */); } if (enb_config->cell_config[0]->has_eutra_band && enb_config->cell_config[0]->has_dl_freq From 21dcd834cc8b502c3397b6ab0525c2b3171da85c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 10 Sep 2020 15:49:17 +0200 Subject: [PATCH 17/22] Save list of SOs used in user plane --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 77 ++++++++++++++++++- .../CONTROL_MODULES/MAC/flexran_agent_mac.h | 6 ++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 3396c05b70..472572f469 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -66,6 +66,9 @@ int xid = 50; struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; +/* a list of shared objects that are loaded into the user plane */ +SLIST_HEAD(flexran_so_handle, flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB]; + int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, @@ -1404,6 +1407,8 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; } } + + SLIST_INIT(&flexran_handles[mod_id]); } /*********************************************** @@ -1902,6 +1907,69 @@ void flexran_agent_slice_update(mid_t mod_id) { apply_update_dl_slice_config(mod_id, sc->dl); apply_update_ul_slice_config(mod_id, sc->ul); helper_destroy_mac_slice_config(sc); + + flexran_agent_so_handle_t *so = NULL; + flexran_agent_so_handle_t *prev = NULL; // the previous to current element, if we delete in order to go back + //SLIST_FOREACH(so, &flexran_handles[mod_id], entries) + for(so = flexran_handles[mod_id].slh_first; so;) { + char *name = so->name; + int in_use = strcmp(flexran_get_dl_scheduler_name(mod_id), name) == 0 + || strcmp(flexran_get_ul_scheduler_name(mod_id), name) == 0; + Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id); + if (!in_use && dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + int n = flexran_get_num_dl_slices(mod_id); + for (int i = 0; i < n; ++i) { + Protocol__FlexSlice s; + /* NONE so it won't do any allocations */ + flexran_get_dl_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None); + if (strcmp(s.scheduler, name) == 0) { + in_use = 1; + break; + } + } + } + Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id); + if (!in_use && ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + int n = flexran_get_num_ul_slices(mod_id); + for (int i = 0; i < n; ++i) { + Protocol__FlexSlice s; + /* NONE so it won't do any allocations */ + flexran_get_ul_slice(mod_id, i, &s, PROTOCOL__FLEX_SLICE_ALGORITHM__None); + if (strcmp(s.scheduler, name) == 0) { + in_use = 1; + break; + } + } + } + if (!in_use) { + char s[512]; + int rc = flexran_agent_map_name_to_delegated_object(mod_id, so->name, s, 512); + LOG_W(FLEXRAN_AGENT, + "removing %s (library handle %p) since it is not used in the user " + "plane anymore\n", + s, + so->dl_handle); + dlclose(so->dl_handle); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, "cannot map name %s\n", so->name); + } else { + int rc = remove(s); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "cannot remove file %s: %s\n", s, strerror(errno)); + } + free (so->name); + if (!prev) { //it's the head, start over + SLIST_REMOVE_HEAD(&flexran_handles[mod_id], entries); + so = flexran_handles[mod_id].slh_first; + } else { + SLIST_REMOVE(&flexran_handles[mod_id], so, flexran_agent_so_handle_s, entries); + so = prev->entries.sle_next; + } + } else { + prev = so; + so = so->entries.sle_next; + } + } } Protocol__FlexUeConfig *ue_config = NULL; @@ -1975,7 +2043,10 @@ void flexran_agent_mac_inform_delegation(mid_t mod_id, * prepare_update_slice_config() takes ownership of the slice config, it is * freed inside */ - - /* TODO save dlhandle in list with name. If it has been installed and nothing - * references it after a reconfiguration, free and remove */ + flexran_agent_so_handle_t *so = malloc(sizeof(flexran_agent_so_handle_t)); + DevAssert(so); + so->name = strdup(cdm->name); + DevAssert(so->name); + so->dl_handle = h; + SLIST_INSERT_HEAD(&flexran_handles[mod_id], so, entries); } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 7eade10c03..4a3e8f5746 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -39,6 +39,12 @@ // for flexran_agent_get_mac_xface() #include "flexran_agent_extern.h" +/* Type for a list of shared objects used in the user plane (schedulers) */ +typedef struct flexran_agent_so_handle_s { + char *name; // name of the object + void *dl_handle; // handle of associated objects + SLIST_ENTRY (flexran_agent_so_handle_s) entries; +} flexran_agent_so_handle_t; /* Initialization function for the agent structures etc */ void flexran_agent_init_mac_agent(mid_t mod_id); From 38ace905aa44b007d62a910a1bd4aac412079ca9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 10 Sep 2020 15:58:03 +0200 Subject: [PATCH 18/22] Check for shared objects beforing setting scheduler --- .../MAC/flexran_agent_mac_internal.c | 44 +++++++++++++++---- openair2/ENB_APP/flexran_agent_ran_api.c | 16 +++---- openair2/ENB_APP/flexran_agent_ran_api.h | 18 ++++---- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 93de0b11ec..b65b197442 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -33,6 +33,9 @@ #include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_slice_verification.h" +extern SLIST_HEAD(flexran_so_handle, + flexran_agent_so_handle_s) flexran_handles[NUM_MAX_ENB]; + Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage *old_message) { @@ -1025,6 +1028,15 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { } +void *search_so(mid_t mod_id, char *name) { + flexran_agent_so_handle_t *so = NULL; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) { + if (strcmp(so->name, name) == 0) + return so->dl_handle; + } + return NULL; +} + void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET && !s->label && !s->scheduler) { @@ -1033,8 +1045,12 @@ void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { if (!rc) LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); } else { - LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id); - const int rc = flexran_create_dl_slice(mod_id, s); + void *lib = search_so(mod_id, s->scheduler); + LOG_I(FLEXRAN_AGENT, + "updating DL slice ID %d (library handle %p)\n", + s->id, + lib); + const int rc = flexran_create_dl_slice(mod_id, s, lib); if (rc < 0) LOG_W(FLEXRAN_AGENT, "error while update slice ID %d: flexran_create_dl_slice() -> %d\n", @@ -1050,8 +1066,12 @@ void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) { if (!rc) LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); } else { - LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id); - const int rc = flexran_create_ul_slice(mod_id, s); + void *lib = search_so(mod_id, s->scheduler); + LOG_I(FLEXRAN_AGENT, + "updating UL slice ID %d (library handle %p)\n", + s->id, + lib); + const int rc = flexran_create_ul_slice(mod_id, s, lib); if (rc < 0) LOG_W(FLEXRAN_AGENT, "error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n", @@ -1099,8 +1119,12 @@ void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *d LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); return; } - LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler); - const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler); + void *lib = search_so(mod_id, dl->scheduler); + LOG_I(FLEXRAN_AGENT, + "loading DL new scheduling algorithm '%s' (library handle %p)\n", + dl->scheduler, + lib); + const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler, lib); if (rc < 0) { LOG_E(FLEXRAN_AGENT, "error while updating scheduling algorithm: " @@ -1147,8 +1171,12 @@ void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *u LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); return; } - LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler); - const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler); + void *lib = search_so(mod_id, ul->scheduler); + LOG_I(FLEXRAN_AGENT, + "loading new UL scheduling algorithm '%s' (library handle %p)\n", + ul->scheduler, + lib); + const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler, lib); if (rc < 0) { LOG_E(FLEXRAN_AGENT, "error while updating scheduling algorithm: " diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 79c992a4d7..afda031b72 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3116,7 +3116,7 @@ void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) ul->move_UE(ul->slices, ue_id, idx); } -int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) { if (!mac_is_present(mod_id)) return 0; void *params = NULL; switch (s->params_case) { @@ -3133,7 +3133,7 @@ int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { char *l = s->label ? strdup(s->label) : NULL; void *algo = &dl->dl_algo; // default scheduler if (s->scheduler) { - algo = dlsym(NULL, s->scheduler); + algo = dlsym(object, s->scheduler); if (!algo) { free(params); LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); @@ -3193,7 +3193,7 @@ int flexran_get_num_dl_slices(mid_t mod_id) { return RC.mac[mod_id]->pre_processor_dl.slices->num; } -int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) { if (!mac_is_present(mod_id)) return -1; void *params = NULL; switch (s->params_case) { @@ -3210,7 +3210,7 @@ int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { char *l = s->label ? strdup(s->label) : NULL; void *algo = &ul->ul_algo; // default scheduler if (s->scheduler) { - algo = dlsym(NULL, s->scheduler); + algo = dlsym(object, s->scheduler); if (!algo) { free(params); LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); @@ -3276,9 +3276,9 @@ char *flexran_get_dl_scheduler_name(mid_t mod_id) { return RC.mac[mod_id]->pre_processor_dl.dl_algo.name; } -int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { +int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object) { if (!mac_is_present(mod_id)) return -1; - void *d = dlsym(NULL, sched); + void *d = dlsym(object, sched); if (!d) return -2; pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl; dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); @@ -3292,9 +3292,9 @@ char *flexran_get_ul_scheduler_name(mid_t mod_id) { return RC.mac[mod_id]->pre_processor_ul.ul_algo.name; } -int flexran_set_ul_scheduler(mid_t mod_id, char *sched) { +int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object) { if (!mac_is_present(mod_id)) return -1; - void *d = dlsym(NULL, sched); + void *d = dlsym(object, sched); if (!d) return -2; pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul; ul_pp->ul_algo.unset(&ul_pp->ul_algo.data); diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 2d8a86f7d0..6abda4dcd6 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -676,8 +676,9 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); /* Set the UL slice for a UE */ void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); -/* Create slice in DL, returns the new slice index */ -int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Create slice in DL, returns the new slice index, object can be shared + * library for the scheduler or NULL */ +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object); /* Remove slice in DL, returns new number of slices or -1 on error */ int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); @@ -691,8 +692,9 @@ void flexran_get_dl_slice(mid_t mod_id, /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); -/* Create slice in UL, returns the new slice index */ -int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Create slice in UL, returns the new slice index, object can be shared library + * for the scheduler or NULL */ +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object); /* Remove slice in UL */ int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); @@ -708,14 +710,14 @@ int flexran_get_num_ul_slices(mid_t mod_id); /* Get the name of/Set the DL scheduling algorithm. If slicing is active, this * corresponds to the default algorithm for slices, otherwise the currently - * used one. */ + * used one. object is a shared object in which to find the scheduler */ char *flexran_get_dl_scheduler_name(mid_t mod_id); -int flexran_set_dl_scheduler(mid_t mod_id, char *sched); +int flexran_set_dl_scheduler(mid_t mod_id, char *sched, void *object); /* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL - * case */ + * case. object is a shared object in which to find the scheduler */ char *flexran_get_ul_scheduler_name(mid_t mod_id); -int flexran_set_ul_scheduler(mid_t mod_id, char *sched); +int flexran_set_ul_scheduler(mid_t mod_id, char *sched, void *object); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ From 28c47996e44261699f8dff7f687933a3a1804cbc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 12 Sep 2020 12:02:54 +0200 Subject: [PATCH 19/22] When preparing slice update/search also loaded libraries --- .../ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c | 11 ++++++++++- .../CONTROL_MODULES/MAC/flexran_agent_mac_internal.c | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 472572f469..117a457b6e 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1728,7 +1728,16 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { } int check_scheduler(mid_t mod_id, char *s) { - return dlsym(NULL, s) != NULL; + if (!s) + return 1; + if (dlsym(NULL, s)) + return 1; + flexran_agent_so_handle_t *so = NULL; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) { + if (strcmp(so->name, s) == 0) + return 1; + } + return 0; } void request_scheduler(mid_t mod_id, char *s, int xid) { diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index b65b197442..42246c3ebf 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -1029,6 +1029,10 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { } void *search_so(mid_t mod_id, char *name) { + if (!name) // no name -> nothing to return, so use NULL for executable + return NULL; + if (dlsym(NULL, name)) // found it in executable + return NULL; flexran_agent_so_handle_t *so = NULL; SLIST_FOREACH(so, &flexran_handles[mod_id], entries) { if (strcmp(so->name, name) == 0) From e5695779447cd7f0ca1b0be56677c475b42848a1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 12 Sep 2020 12:57:30 +0200 Subject: [PATCH 20/22] FlexRAN: send loaded apps/macObjects to RTC --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 18 ++++++++++++++++++ .../CONTROL_MODULES/MAC/flexran_agent_mac.h | 5 +++++ openair2/ENB_APP/MESSAGES/V2/flexran.proto | 2 ++ openair2/ENB_APP/flexran_agent_app.c | 17 +++++++++++++++++ openair2/ENB_APP/flexran_agent_app.h | 4 ++++ openair2/ENB_APP/flexran_agent_common.c | 10 ++++++++++ 6 files changed, 56 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 117a457b6e..7ca466e8ff 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -2059,3 +2059,21 @@ void flexran_agent_mac_inform_delegation(mid_t mod_id, so->dl_handle = h; SLIST_INSERT_HEAD(&flexran_handles[mod_id], so, entries); } + +void flexran_agent_mac_fill_loaded_mac_objects( + mid_t mod_id, + Protocol__FlexEnbConfigReply *reply) { + int n = 0; + flexran_agent_so_handle_t *so = NULL; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) + ++n; + reply->n_loadedmacobjects = n; + reply->loadedmacobjects = calloc(n, sizeof(char *)); + if (!reply->loadedmacobjects) { + reply->n_loadedmacobjects = 0; + return; + } + n = 0; + SLIST_FOREACH(so, &flexran_handles[mod_id], entries) + reply->loadedmacobjects[n++] = so->name; +} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 4a3e8f5746..18e567c061 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -139,4 +139,9 @@ void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); void flexran_agent_mac_inform_delegation(mid_t mod_id, Protocol__FlexControlDelegation *cdm); +/* fill the enb_config_reply with the shared objects in use by the MAC sublayer */ +void flexran_agent_mac_fill_loaded_mac_objects( + mid_t mod_id, + Protocol__FlexEnbConfigReply *reply); + #endif diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 7fd19c805c..cec7f84b6e 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -159,6 +159,8 @@ message flex_enb_config_reply { repeated flex_cell_config cell_config = 3; optional uint32 device_spec = 4; optional flex_s1ap_config s1ap = 5; + repeated string loadedApps = 6; + repeated string loadedMacObjects = 7; } message flex_ue_config_request { diff --git a/openair2/ENB_APP/flexran_agent_app.c b/openair2/ENB_APP/flexran_agent_app.c index fd6a51c97e..5bf06ca631 100644 --- a/openair2/ENB_APP/flexran_agent_app.c +++ b/openair2/ENB_APP/flexran_agent_app.c @@ -188,3 +188,20 @@ void flexran_agent_handle_apps( } } } + +void flexran_agent_fill_loaded_apps(mid_t mod_id, + Protocol__FlexEnbConfigReply *reply) { + int n = 0; + flexran_agent_app_internal_t *so = NULL; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) + ++n; + reply->n_loadedapps = n; + reply->loadedapps = calloc(n, sizeof(char *)); + if (!reply->loadedapps) { + reply->n_loadedapps = 0; + return; + } + n = 0; + SLIST_FOREACH(so, &flexran_apps[mod_id], entries) + reply->loadedapps[n++] = so->name; +} diff --git a/openair2/ENB_APP/flexran_agent_app.h b/openair2/ENB_APP/flexran_agent_app.h index f5e1fe54c3..4723b344bf 100644 --- a/openair2/ENB_APP/flexran_agent_app.h +++ b/openair2/ENB_APP/flexran_agent_app.h @@ -67,4 +67,8 @@ void flexran_agent_handle_apps( Protocol__FlexAgentReconfigurationSubsystem **subs, int n_subs); +/* Fills the enb_config_reply with the currently loaded (started) apps */ +void flexran_agent_fill_loaded_apps(mid_t mod_id, + Protocol__FlexEnbConfigReply *reply); + #endif diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 345cb5ad96..abb5b57e0c 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -330,6 +330,12 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { if (reply->s1ap) flexran_agent_free_s1ap_cell_config(&reply->s1ap); + if (reply->loadedapps) + free(reply->loadedapps); + + if (reply->loadedmacobjects) + free(reply->loadedmacobjects); + free(reply->cell_config); free(reply); free(msg); @@ -836,6 +842,10 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F if (flexran_agent_get_s1ap_xface(mod_id)) flexran_agent_fill_s1ap_cell_config(mod_id, &enb_config_reply_msg->s1ap); + flexran_agent_fill_loaded_apps(mod_id, enb_config_reply_msg); + + flexran_agent_mac_fill_loaded_mac_objects(mod_id, enb_config_reply_msg); + *msg = malloc(sizeof(Protocol__FlexranMessage)); if(*msg == NULL) { From f146b640d528d1eb67e1eedaa121d7bb1a665bab Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 21 Aug 2020 12:50:07 +0200 Subject: [PATCH 21/22] FlexRAN agent app: trigger UE-slice assoc through IMSI regex --- cmake_targets/CMakeLists.txt | 5 + openair2/ENB_APP/flexran_agent.c | 1 - openair2/ENB_APP/flexran_agent_ran_api.c | 14 +- openair2/ENB_APP/flexran_agent_ran_api.h | 4 +- openair2/ENB_APP/flexran_apps/imsi.c | 245 +++++++++++++++++++++++ 5 files changed, 260 insertions(+), 9 deletions(-) create mode 100644 openair2/ENB_APP/flexran_apps/imsi.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index f213c7380d..e9354c39de 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1103,8 +1103,13 @@ add_library(flapp_sample SHARED ${OPENAIR2_DIR}/ENB_APP/flexran_apps/sample.c ) set_target_properties(flapp_sample PROPERTIES C_VISIBILITY_PRESET hidden) +add_library(flapp_imsi SHARED + ${OPENAIR2_DIR}/ENB_APP/flexran_apps/imsi.c +) +set_target_properties(flapp_imsi PROPERTIES C_VISIBILITY_PRESET hidden) add_custom_target(flapp_all DEPENDS flapp_sample + flapp_imsi ) #include_directories(${OPENAIR2_DIR}/ENB_APP) diff --git a/openair2/ENB_APP/flexran_agent.c b/openair2/ENB_APP/flexran_agent.c index 78e5ce8dde..7d4546815f 100644 --- a/openair2/ENB_APP/flexran_agent.c +++ b/openair2/ENB_APP/flexran_agent.c @@ -115,7 +115,6 @@ error: return NULL; } - int channel_container_init = 0; int flexran_agent_start(mid_t mod_id) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index afda031b72..d126012737 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3092,12 +3092,13 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { return slices->s[idx]->id; } -void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; +int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return 0; int idx = flexran_find_dl_slice(mod_id, slice_id); - if (idx < 0) return; + if (idx < 0) return 0; pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; dl->move_UE(dl->slices, ue_id, idx); + return 1; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { @@ -3108,12 +3109,13 @@ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { return slices->s[idx]->id; } -void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; +int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return 0; int idx = flexran_find_ul_slice(mod_id, slice_id); - if (idx < 0) return; + if (idx < 0) return 0; pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; ul->move_UE(ul->slices, ue_id, idx); + return 1; } int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s, void *object) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 6abda4dcd6..79115b0a16 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -669,12 +669,12 @@ int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); /* Set the DL slice for a UE */ -void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); +int flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); /* Set the UL slice for a UE */ -void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); +int flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Create slice in DL, returns the new slice index, object can be shared * library for the scheduler or NULL */ diff --git a/openair2/ENB_APP/flexran_apps/imsi.c b/openair2/ENB_APP/flexran_apps/imsi.c new file mode 100644 index 0000000000..b986f27a0a --- /dev/null +++ b/openair2/ENB_APP/flexran_apps/imsi.c @@ -0,0 +1,245 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file imsi.c + * \brief flexran IMSI UE-slice association app + * \author Robert Schmidt, Firas Abdeljelil + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include +#include "flexran_agent_common.h" +#include "flexran_agent_async.h" +#include "flexran_agent_extern.h" +#include "flexran_agent_timer.h" +#include "flexran_agent_defs.h" +#include "flexran_agent_net_comm.h" +#include "flexran_agent_ran_api.h" +#include "flexran_agent_phy.h" +#include "flexran_agent_mac.h" +#include "flexran_agent_rrc.h" +#include "flexran_agent_pdcp.h" +#include "flexran_agent_s1ap.h" +#include "flexran_agent_app.h" +#include "common/utils/LOG/log.h" +#include "assertions.h" +#include "queue.h" +typedef struct Map_regex_slice slist_data_t; +struct Map_regex_slice { + char regex_[30] ; + int slice_dl; + int slice_ul; + regex_t regex; + SLIST_ENTRY (Map_regex_slice) entries; +}; +bool reconfig = false; +int ue[MAX_MOBILES_PER_ENB]={ [0 ... MAX_MOBILES_PER_ENB - 1] = -1 }; + +SLIST_HEAD(slisthead, Map_regex_slice) head; + +int dump_list(void) { + int len = 1; + slist_data_t *datap = NULL; + SLIST_FOREACH(datap, &head, entries) { + LOG_W(FLEXRAN_AGENT, "%d: regex %s DL %d UL %d\n", len++, datap->regex_, + datap->slice_dl, datap->slice_ul); + } + return len; +} + +void ajout(char *regex, int dl, int ul) { + slist_data_t *datap = malloc(sizeof(slist_data_t)); + if (!datap) { + LOG_E(FLEXRAN_AGENT, "cannot allocate memory for slist_data_t\n"); + return; + } + strcpy(datap->regex_, regex); + datap->slice_dl = dl; + datap->slice_ul = ul; + regcomp(&datap->regex, datap->regex_, 0); + SLIST_INSERT_HEAD(&head, datap, entries); + if (ul==-1) + LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d\n" ,regex, dl); + else if (dl==-1) + LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice UL %d\n" ,regex, ul); + else + LOG_I(FLEXRAN_AGENT, "added new element to list: regex %s slice DL %d UL %d\n", + regex, dl, ul); +} +void remove_(char *regex) { + slist_data_t *datap = NULL; + SLIST_FOREACH(datap, &head, entries) { + if (strcmp(datap->regex_, regex) == 0) { + SLIST_REMOVE(&head, datap, Map_regex_slice, entries); + if (datap->slice_dl==-1) + LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice UL %d\n",datap->regex_, datap->slice_ul); + else if (datap->slice_ul==-1) + LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d\n",datap->regex_, datap->slice_dl); + else + LOG_I(FLEXRAN_AGENT, "removed element from list: regex %s slice DL %d UL %d\n", + datap->regex_, datap->slice_dl, datap->slice_ul); + regfree(&datap->regex); + free(datap); + return; + } + } + LOG_E(FLEXRAN_AGENT, "no regex %s found in list\n", regex); +} + +Protocol__FlexranMessage *matching_tick( + mid_t mod_id, + const Protocol__FlexranMessage *msg) { + const int num = flexran_get_mac_num_ues(mod_id); + for (int i = 0; i < num; i++) { + int ue_id = flexran_get_mac_ue_id(mod_id, i); + if (ue[ue_id] >= 0 && !reconfig) + continue; + rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); + uint64_t imsi = flexran_get_ue_imsi(mod_id, rnti); + char snum[20]; + sprintf(snum, "%" PRIu64, imsi); + slist_data_t *datap = NULL; + SLIST_FOREACH(datap, &head, entries) { + if (regexec(&datap->regex, snum, 0, NULL, 0) == 0) { + + int dl = datap->slice_dl; + if (dl >= 0 && dl != flexran_get_ue_dl_slice_id(mod_id, ue_id)) { + int ra = flexran_set_ue_dl_slice_id(mod_id, ue_id, dl); + if (ra) + LOG_I(FLEXRAN_AGENT, + "RNTI %04x/IMSI %s in the slice_dl %d\n", + rnti, + snum, + dl); + else + LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl); + } + + int ul = datap->slice_ul; + if (ul >= 0 && ul != flexran_get_ue_ul_slice_id(mod_id, ue_id)) { + int rb = flexran_set_ue_ul_slice_id(mod_id, ue_id, ul); + if (rb) + LOG_I(FLEXRAN_AGENT, + "RNTI %04x/IMSI %s in the slice_ul %d\n", + rnti, + snum, + ul); + else + LOG_W(FLEXRAN_AGENT, "No such DL slice %d\n", dl); + } + } + } + ue[ue_id] = ue_id; + } + reconfig = false; + return NULL; +} +void ajout_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { + char s[30]; + reconfig = true; + bool supp=false; + bool sl_E=false; + int dl=-1; + int ul=-1; + slist_data_t *datap = NULL; + for (int i = 0; i < n_p; ++i) { + switch (p[i]->value->param_case) { + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM__NOT_SET: + LOG_I(FLEXRAN_AGENT, " param %s is not set\n", p[i]->key); + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_INTEGER: + if( strcmp(p[i]->key, "slice_dl")==0) + dl= p[i]->value->integer; + else + ul= p[i]->value->integer; + sl_E=true; + break; + case PROTOCOL__FLEX_AGENT_RECONFIGURATION_PARAM__PARAM_STR: + strcpy(s,p[i]->value->str); + break; + default: + LOG_W(FLEXRAN_AGENT, " type of param %s is unknown\n", p[i]->key); + break; + }; + } + if (!SLIST_EMPTY(&head)){ + SLIST_FOREACH(datap, &head, entries) { + if (strcmp(datap->regex_, s) == 0) { + if (datap->slice_dl!=dl || datap->slice_ul!=ul) + supp=true; + } + } + } + if (sl_E==false) + remove_(s); + else { + if (supp==true) + remove_(s); + ajout(s,dl,ul); + } + /* re-verify all UEs again */ + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + ue[i] = -1; +} +/* imsi_start: entry point for imsi app. Installs a callback using the timer + * API to have function imsi_tick() called every 5s */ +#define TIMER 32 +int imsi_start(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) +{ + LOG_W(FLEXRAN_AGENT, "%s(): enable IMSI app timer\n", __func__); + flexran_agent_create_timer(mod_id, + 500, + FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, + TIMER, + matching_tick, + NULL); + SLIST_INIT(&head); + return 0; +} + +int imsi_reconfig(mid_t mod_id, + Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, + int n_p) +{ + ajout_param(p, n_p); + return 0; +} + +/* stop function: cleans up before app can be unloaded. Here: stop the timer */ +int imsi_stop(mid_t mod_id) { + LOG_W(FLEXRAN_AGENT, "%s(): disable IMSI app timer\n", __func__); + flexran_agent_destroy_timer(mod_id, TIMER); + + return 0; +} + +/* app definition. visibility should be set to default so this symbol is + * reachable from outside */ +flexran_agent_app_t __attribute__ ((visibility ("default"))) app = { + .start = imsi_start, + .reconfig = imsi_reconfig, + .stop = imsi_stop +}; From 8cb530d25c6a84fecbf51813f2e322ff467f6822 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 9 Oct 2020 09:02:59 +0200 Subject: [PATCH 22/22] Address review in !913: rename functions --- openair2/ENB_APP/flexran_apps/imsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/ENB_APP/flexran_apps/imsi.c b/openair2/ENB_APP/flexran_apps/imsi.c index b986f27a0a..6f75033f38 100644 --- a/openair2/ENB_APP/flexran_apps/imsi.c +++ b/openair2/ENB_APP/flexran_apps/imsi.c @@ -68,7 +68,7 @@ int dump_list(void) { return len; } -void ajout(char *regex, int dl, int ul) { +void add(char *regex, int dl, int ul) { slist_data_t *datap = malloc(sizeof(slist_data_t)); if (!datap) { LOG_E(FLEXRAN_AGENT, "cannot allocate memory for slist_data_t\n"); @@ -155,7 +155,7 @@ Protocol__FlexranMessage *matching_tick( reconfig = false; return NULL; } -void ajout_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { +void add_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { char s[30]; reconfig = true; bool supp=false; @@ -196,7 +196,7 @@ void ajout_param(Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, i else { if (supp==true) remove_(s); - ajout(s,dl,ul); + add(s,dl,ul); } /* re-verify all UEs again */ for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) @@ -224,7 +224,7 @@ int imsi_reconfig(mid_t mod_id, Protocol__FlexAgentReconfigurationSubsystem__ParamsEntry **p, int n_p) { - ajout_param(p, n_p); + add_param(p, n_p); return 0; }