Merge remote-tracking branch 'origin/develop' into NR_FAPI_beamindex_SSB_RO

This commit is contained in:
Florian Kaltenberger
2020-11-10 21:46:52 +01:00
212 changed files with 16575 additions and 7521 deletions
-13
View File
@@ -65,18 +65,6 @@
#define MAX_NR_RRC_UE_CONTEXTS 64
#ifndef UE_EXPANSION
// TODO:L2 FAPI simulator.
// UESIM_EXPANSION is used to be same value of MAX_MOBILES_PER_ENB
// in eNB and UE.
// now , if we use --mu option in UE, compiling error will occur.
// This problem will be fixed in the future.
#ifdef UESIM_EXPANSION
#define MAX_MOBILES_PER_ENB 256
#define MAX_MOBILES_PER_ENB_NB_IoT 256
#define MAX_MOBILES_PER_GNB 256
#define MAX_eNB 2
#define MAX_gNB 2
#else
#ifdef LARGE_SCALE
#define MAX_MOBILES_PER_ENB 128
#define MAX_MOBILES_PER_ENB_NB_IoT 128
@@ -90,7 +78,6 @@
#define MAX_eNB 2
#define MAX_gNB 2
#endif
#endif
#else
#define MAX_MOBILES_PER_ENB 256
#define MAX_MOBILES_PER_ENB_NB_IoT 256
@@ -40,6 +40,8 @@
#include "common/utils/LOG/log.h"
#include <dlfcn.h>
/*Array containing the Agent-MAC interfaces*/
AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
@@ -53,10 +55,20 @@ 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];
/* 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,
@@ -1363,6 +1375,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,
@@ -1382,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]);
}
/***********************************************
@@ -1659,6 +1686,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,7 +1727,81 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) {
flexran_agent_destroy_mac_slice_config(&helper);
}
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) {
int check_scheduler(mid_t mod_id, char *s) {
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) {
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,
int request_objects) {
if (!*slice_config) return;
/* just use the memory and set to NULL in original */
Protocol__FlexSliceConfig *sc = *slice_config;
@@ -1709,6 +1812,63 @@ 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 (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; 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++);
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,
@@ -1756,6 +1916,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;
@@ -1765,3 +1988,92 @@ 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 */
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);
}
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;
}
@@ -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);
@@ -117,7 +123,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 +135,13 @@ 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);
/* 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
@@ -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,19 @@ 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)
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 +1049,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 +1070,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 +1123,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 +1175,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: "
@@ -3,4 +3,25 @@ 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
}
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<string, flex_agent_reconfiguration_param> 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;
}
}
+12 -1
View File
@@ -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;
}
}
@@ -157,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 {
@@ -225,11 +229,17 @@ 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
}
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
//
@@ -237,6 +247,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
@@ -44,5 +44,6 @@ enum flex_type {
FLPT_RECONFIGURE_AGENT = 16;
FLPT_RRC_TRIGGERING = 17;
FLPT_UL_MAC_CONFIG = 18;
FLPT_DELEGATE_REQUEST = 22;
}
+3 -1
View File
@@ -115,7 +115,6 @@ error:
return NULL;
}
int channel_container_init = 0;
int flexran_agent_start(mid_t mod_id)
{
@@ -233,6 +232,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);
+1
View File
@@ -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"
+207
View File
@@ -0,0 +1,207 @@
/*
* 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 <dlfcn.h>
/* 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);
}
}
}
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;
}
+74
View File
@@ -0,0 +1,74 @@
/*
* 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);
/* 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
+116 -18
View File
@@ -29,6 +29,9 @@
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <errno.h>
#include "flexran_agent_common.h"
#include "flexran_agent_common_internal.h"
@@ -39,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"
@@ -326,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);
@@ -424,26 +434,65 @@ 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 name\n");
return 0;
}
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 {
if (errno == EEXIST) {
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;
}
} else {
LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n",
mod_id, target);
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));
}
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);
}
// long time_elapsed_nanos = timer_end(vartime);
*msg = NULL;
return 0;
}
@@ -452,10 +501,44 @@ int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg) {
return 0;
}
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 >= maxlen) {
LOG_E(FLEXRAN_AGENT, "path has been truncated, cannot read object\n");
return -1;
}
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) {
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;
}
@@ -465,6 +548,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;
@@ -750,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) {
@@ -880,7 +976,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
+9
View File
@@ -131,11 +131,20 @@ 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);
/* 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);
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);
+6
View File
@@ -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"
@@ -80,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[] = { */
+16 -14
View File
@@ -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,15 +3109,16 @@ 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) {
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 +3135,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 +3195,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 +3212,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 +3278,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 +3294,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);
+12 -10
View File
@@ -669,15 +669,16 @@ 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 */
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 */
+33 -27
View File
@@ -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,45 +245,35 @@ err_code_t flexran_agent_create_timer(mid_t mod_id,
struct timesync *sync = &timesync[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;
}
/* 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);
return 0;
}
err_code_t flexran_agent_destroy_timers(mid_t mod_id) {
struct timesync *sync = &timesync[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);
}
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;
}
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
struct timesync *sync = &timesync[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;
}
@@ -277,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];
-3
View File
@@ -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);
+245
View File
@@ -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 <stdio.h>
#include <stdlib.h>
#include <regex.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 "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 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");
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 add_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);
add(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)
{
add_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
};
+121
View File
@@ -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
};
@@ -56,6 +56,8 @@
#include "flexran.pb-c.h"
#include "flexran_agent_mac.h"
#include <dlfcn.h>
#include <openair2/LAYER2/MAC/mac.h>
#include "T.h"
-11
View File
@@ -44,7 +44,6 @@
#include "common/ran_context.h"
extern FILL_UL_INFO_MUTEX_t fill_ul_mutex;
extern void openair_rrc_top_init_ue( int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active);
void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync) { //init as MR
@@ -90,16 +89,6 @@ mac_top_init_ue(int eMBMS_active, char *uecap_xer,
UE_mac_inst = NULL;
}
// mutex below are used for multiple UE's L2 FAPI simulation.
if (NFAPI_MODE == NFAPI_UE_STUB_PNF) {
pthread_mutex_init(&fill_ul_mutex.rx_mutex,NULL);
pthread_mutex_init(&fill_ul_mutex.crc_mutex,NULL);
pthread_mutex_init(&fill_ul_mutex.sr_mutex,NULL);
pthread_mutex_init(&fill_ul_mutex.harq_mutex,NULL);
pthread_mutex_init(&fill_ul_mutex.cqi_mutex,NULL);
pthread_mutex_init(&fill_ul_mutex.rach_mutex,NULL);
}
LOG_I(MAC, "[MAIN] calling RRC\n");
openair_rrc_top_init_ue(eMBMS_active, uecap_xer, cba_group_active,
HO_active);
+107 -151
View File
@@ -69,6 +69,70 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) {
return RBGsize;
}
bool try_allocate_harq_retransmission(module_id_t Mod_id,
int CC_id,
int frame,
int subframe,
int UE_id,
int start_rbg,
int *n_rbg_sched,
uint8_t *rbgalloc_mask) {
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
// check whether there are HARQ retransmissions
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
// retransmission: allocate
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
if (nb_rb == 0) {
return false;
}
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
// needs more RBGs than we can allocate
if (nb_rbg > *n_rbg_sched) {
LOG_D(MAC,
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
UE_id, nb_rbg, *n_rbg_sched);
return false;
}
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
// if we allocate the last RBG this one should have the full RBGsize
if ((nb_rb % RBGsize) == 0 && nb_rbg == *n_rbg_sched
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
LOG_D(MAC,
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
return false;
}
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
if (idx < 0) { // cannot allocate CCE
LOG_D(MAC, "cannot allocate UE %d: no CCE can be allocated\n", UE_id);
return false;
}
ue_ctrl->pre_dci_dl_pdu_idx = idx;
// retransmissions: directly allocate
*n_rbg_sched -= nb_rbg;
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
for (; nb_rbg > 0; start_rbg++) {
if (!rbgalloc_mask[start_rbg])
continue;
ue_ctrl->rballoc_sub_UE[CC_id][start_rbg] = 1;
rbgalloc_mask[start_rbg] = 0;
nb_rbg--;
}
LOG_D(MAC,
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
"retx nb_rb %d pre_nb_available_rbs %d\n",
frame, subframe, *n_rbg_sched, UE_id,
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
ue_ctrl->pre_nb_available_rbs[CC_id]);
return true;
}
void *rr_dl_setup(void) {
void *data = malloc(sizeof(int));
*(int *) data = 0;
@@ -115,64 +179,25 @@ int rr_dl_run(module_id_t Mod_id,
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
if (round != 8) { // retransmission: allocate
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
if (nb_rb == 0)
goto skip_ue;
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
// needs more RBGs than we can allocate
if (nb_rbg > n_rbg_sched) {
LOG_D(MAC,
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
UE_id, nb_rbg, n_rbg_sched);
goto skip_ue;
if (round != 8) {
bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
UE_id, rbg, &n_rbg_sched,
rbgalloc_mask);
if (r) {
/* if there are no more RBG to give, return */
if (n_rbg_sched <= 0)
return 0;
max_num_ue--;
if (max_num_ue == 0)
return n_rbg_sched;
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
}
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
// if we allocate the last RBG this one should have the full RBGsize
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
LOG_D(MAC,
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
goto skip_ue;
}
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
if (idx < 0)
goto skip_ue; // cannot allocate CCE
ue_ctrl->pre_dci_dl_pdu_idx = idx;
// retransmissions: directly allocate
n_rbg_sched -= nb_rbg;
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
for (; nb_rbg > 0; rbg++) {
if (!rbgalloc_mask[rbg])
continue;
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
rbgalloc_mask[rbg] = 0;
nb_rbg--;
}
LOG_D(MAC,
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
frame, subframe, n_rbg_sched, UE_id, round,
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
ue_ctrl->pre_nb_available_rbs[CC_id]);
/* if there are no more RBG to give, return */
if (n_rbg_sched <= 0)
return 0;
max_num_ue--;
/* if there are no UEs that can be allocated anymore, return */
if (max_num_ue == 0)
return n_rbg_sched;
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
} else {
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) {
*cur_UE = UE_id;
cur_UE = &UE_sched.next[UE_id];
}
}
skip_ue:
UE_id = next_ue_list_looped(UE_list, UE_id);
} while (UE_id != *start_ue);
*cur_UE = -1; // mark end
@@ -187,11 +212,12 @@ skip_ue:
cur_UE = &UE_sched.head;
while (*cur_UE >= 0 && max_num_ue > 0) {
const int UE_id = *cur_UE;
cur_UE = &UE_sched.next[UE_id]; // go to next
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
if (idx < 0) {
LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
// SKIP this UE in the list by marking the next as the current
*cur_UE = UE_sched.next[UE_id];
continue;
}
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
@@ -200,6 +226,7 @@ skip_ue:
const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total;
rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize);
max_num_ue--;
cur_UE = &UE_sched.next[UE_id]; // go to next
}
*cur_UE = -1; // not all UEs might be allocated, mark end
@@ -284,56 +311,19 @@ int pf_wbcqi_dl_run(module_id_t Mod_id,
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
if (round != 8) { // retransmission: allocate
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
if (nb_rb == 0)
continue;
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
// needs more RBGs than we can allocate
if (nb_rbg > n_rbg_sched) {
LOG_D(MAC,
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
UE_id, nb_rbg, n_rbg_sched);
continue;
if (round != 8) {
bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
UE_id, rbg, &n_rbg_sched,
rbgalloc_mask);
if (r) {
/* if there are no more RBG to give, return */
if (n_rbg_sched <= 0)
return 0;
max_num_ue--;
if (max_num_ue == 0)
return n_rbg_sched;
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
}
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
// if we allocate the last RBG this one should have the full RBGsize
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
LOG_D(MAC,
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
continue;
}
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
if (idx < 0)
continue; // cannot allocate CCE
ue_ctrl->pre_dci_dl_pdu_idx = idx;
// retransmissions: directly allocate
n_rbg_sched -= nb_rbg;
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
for (; nb_rbg > 0; rbg++) {
if (!rbgalloc_mask[rbg])
continue;
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
rbgalloc_mask[rbg] = 0;
nb_rbg--;
}
LOG_D(MAC,
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
frame, subframe, n_rbg_sched, UE_id, round,
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
ue_ctrl->pre_nb_available_rbs[CC_id]);
/* if there are no more RBG to give, return */
if (n_rbg_sched <= 0)
return 0;
max_num_ue--;
/* if there are no UEs that can be allocated anymore, return */
if (max_num_ue == 0)
return n_rbg_sched;
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
} else {
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
continue;
@@ -436,56 +426,19 @@ int mt_wbcqi_dl_run(module_id_t Mod_id,
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
if (round != 8) { // retransmission: allocate
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
if (nb_rb == 0)
continue;
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
// needs more RBGs than we can allocate
if (nb_rbg > n_rbg_sched) {
LOG_D(MAC,
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
UE_id, nb_rbg, n_rbg_sched);
continue;
if (round != 8) {
bool r = try_allocate_harq_retransmission(Mod_id, CC_id, frame, subframe,
UE_id, rbg, &n_rbg_sched,
rbgalloc_mask);
if (r) {
/* if there are no more RBG to give, return */
if (n_rbg_sched <= 0)
return 0;
max_num_ue--;
if (max_num_ue == 0)
return n_rbg_sched;
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
}
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
// if we allocate the last RBG this one should have the full RBGsize
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
LOG_D(MAC,
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
continue;
}
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
if (idx < 0)
continue; // cannot allocate CCE
ue_ctrl->pre_dci_dl_pdu_idx = idx;
// retransmissions: directly allocate
n_rbg_sched -= nb_rbg;
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
for (; nb_rbg > 0; rbg++) {
if (!rbgalloc_mask[rbg])
continue;
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
rbgalloc_mask[rbg] = 0;
nb_rbg--;
}
LOG_D(MAC,
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
frame, subframe, n_rbg_sched, UE_id, round,
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
ue_ctrl->pre_nb_available_rbs[CC_id]);
/* if there are no more RBG to give, return */
if (n_rbg_sched <= 0)
return 0;
max_num_ue--;
/* if there are no UEs that can be allocated anymore, return */
if (max_num_ue == 0)
return n_rbg_sched;
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
} else {
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
continue;
@@ -942,7 +895,10 @@ int rr_ul_run(module_id_t Mod_id,
&tx_power);
UE_template->pre_assigned_mcs_ul = mcs;
rb_idx_required[UE_id] = rb_table_index;
/* rb_idx_given >= 22: apparently the PHY cannot support more than 48
* RBs in the uplink. Hence, we limit every UE to 48 RBs, which is at
* index 22 */
rb_idx_required[UE_id] = min(22, rb_table_index);
//UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index];
/* only print log when PHR changed */
static int phr = 0;
+4
View File
@@ -336,6 +336,8 @@ void static_dl(module_id_t mod_id,
rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg];
n_rbg_sched += rbgalloc_mask[rbg];
}
if (n_rbg_sched == 0) /* no free RBGs, e.g., taken by RA */
continue;
s->s[i]->dl_algo.run(mod_id,
CC_id,
@@ -445,6 +447,8 @@ void static_ul(module_id_t mod_id,
}
if (!last_rb_blocked)
rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1;
if (n_contig == 1 && rbs[0].length == 0) /* no RBs, e.g., taken by RA */
continue;
s->s[i]->ul_algo.run(mod_id,
CC_id,
+57 -24
View File
@@ -947,6 +947,24 @@ int get_format0(uint8_t index,
return format;
}
int64_t *get_prach_config_info(uint32_t pointa,
uint8_t index,
uint8_t unpaired) {
int64_t *prach_config_info_p;
if (pointa > 2016666) { //FR2
prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index];
}
else { // FR1
if (unpaired)
prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index];
else
prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index];
} // FR2 / FR1
return prach_config_info_p;
}
void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
uint16_t *slot_period,
uint16_t *offset) {
@@ -1451,7 +1469,7 @@ nr_bandentry_t nr_bandtable[] = {
{5, 824000, 849000, 869000, 894000, 20, 173800, 100},
{7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
{8, 880000, 915000, 925000, 960000, 20, 185000, 100},
{12, 698000, 716000, 728000, 746000, 20, 145800, 100},
{12, 698000, 716000, 729000, 746000, 20, 145800, 100},
{20, 832000, 862000, 791000, 821000, 20, 158200, 100},
{25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
{28, 703000, 758000, 758000, 813000, 20, 151600, 100},
@@ -1473,22 +1491,22 @@ nr_bandentry_t nr_bandtable[] = {
{77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30},
{78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15},
{78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30},
{79, 4400000, 5000000, 4400000, 5000000, 1, 693334, 15},
{79, 4400000, 5000000, 4400000, 5000000, 2, 693334, 30},
{79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15},
{79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30},
{80, 1710000, 1785000, 000, 000, 20, 342000, 100},
{81, 860000, 915000, 000, 000, 20, 176000, 100},
{81, 880000, 915000, 000, 000, 20, 176000, 100},
{82, 832000, 862000, 000, 000, 20, 166400, 100},
{83, 703000, 748000, 000, 000, 20, 140600, 100},
{84, 1920000, 1980000, 000, 000, 20, 384000, 100},
{86, 1710000, 1785000, 000, 000, 20, 342000, 100},
{257,26500000,29500000,26500000,29500000, 1,2054166, 60},
{257,26500000,29500000,26500000,29500000, 2,2054167, 120},
{258,24250000,27500000,24250000,27500000, 1,2016667, 60},
{258,24250000,27500000,24250000,27500000, 2,2016667, 120},
{260,37000000,40000000,37000000,40000000, 1,2229166, 60},
{260,37000000,40000000,37000000,40000000, 2,2229167, 120},
{261,27500000,28350000,27500000,28350000, 1,2070833, 60},
{261,27500000,28350000,27500000,28350000, 2,2070833, 120}
{257,26500020,29500000,26500020,29500000, 1,2054166, 60},
{257,26500080,29500000,26500080,29500000, 2,2054167, 120},
{258,24250080,27500000,24250080,27500000, 1,2016667, 60},
{258,24250080,27500000,24250080,27500000, 2,2016667, 120},
{260,37000020,40000000,37000020,40000000, 1,2229166, 60},
{260,37000080,40000000,37000080,40000000, 2,2229167, 120},
{261,27500040,28350000,27500040,28350000, 1,2070833, 60},
{261,27500040,28350000,27500040,28350000, 2,2070833, 120}
};
@@ -1718,13 +1736,23 @@ uint32_t to_nrarfcn(int nr_bandP,
(long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz));
int deltaFglobal = 60;
uint32_t N_REF_Offs = 2016667;
uint64_t F_REF_Offs_khz = 24250080;
if (dl_CarrierFreq < 3e9) deltaFglobal = 15;
if (dl_CarrierFreq < 24.25e9) deltaFglobal = 5;
if (dl_CarrierFreq < 24.25e9) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (dl_CarrierFreq < 3e9) {
deltaFglobal = 5;
N_REF_Offs = 0;
F_REF_Offs_khz = 0;
}
// This is equation before Table 5.4.2.1-1 in 38101-1-f30
// F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs)
nrarfcn = (((dl_CarrierFreq_by_1k - nr_bandtable[i].dl_min)/deltaFglobal)+nr_bandtable[i].N_OFFs_DL);
nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz)/deltaFglobal)+N_REF_Offs);
delta_arfcn = nrarfcn - nr_bandtable[i].N_OFFs_DL;
if(delta_arfcn%(nr_bandtable[i].step_size)!=0)
@@ -1741,13 +1769,21 @@ uint64_t from_nrarfcn(int nr_bandP,
{
int i;
int deltaFglobal = 5;
uint32_t N_REF_Offs = 0;
uint64_t F_REF_Offs_khz = 0;
int scs_khz = 15<<scs_index;
uint32_t delta_arfcn;
if (dl_nrarfcn > 599999 && dl_nrarfcn < 2016667)
deltaFglobal = 15;
if (dl_nrarfcn > 2016666 && dl_nrarfcn < 3279166)
if (dl_nrarfcn > 599999 && dl_nrarfcn < 2016667) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (dl_nrarfcn > 2016666 && dl_nrarfcn < 3279166) {
deltaFglobal = 60;
N_REF_Offs = 2016667;
F_REF_Offs_khz = 24250080;
}
AssertFatal(nr_bandP <= 261, "nr_band %d > 260\n", nr_bandP);
for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++);
@@ -1761,14 +1797,11 @@ uint64_t from_nrarfcn(int nr_bandP,
if(delta_arfcn%(nr_bandtable[i].step_size)!=0)
AssertFatal(1==0,"dl_nrarfcn %u is not on the raster for step size %lu",dl_nrarfcn,nr_bandtable[i].step_size);
LOG_I(PHY,"Computing dl_frequency (pointA %llu => %llu (dlmin %llu, nr_bandtable[%d].N_OFFs_DL %llu))\n",
LOG_I(PHY,"Computing dl_frequency (arfcn %llu => %llu)\n",
(unsigned long long)dl_nrarfcn,
(unsigned long long)(1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal)),
(unsigned long long)nr_bandtable[i].dl_min,
i,
(unsigned long long)nr_bandtable[i].N_OFFs_DL);
(unsigned long long)(1000*(F_REF_Offs_khz + (dl_nrarfcn - N_REF_Offs) * deltaFglobal)));
return 1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal);
return 1000*(F_REF_Offs_khz + (dl_nrarfcn - N_REF_Offs) * deltaFglobal);
}
@@ -36,6 +36,36 @@
#include "NR_CellGroupConfig.h"
#include "nr_mac.h"
// ===============================================
// SSB to RO mapping public defines and structures
// ===============================================
#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO
#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot
#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot
// PRACH occasion details
typedef struct prach_occasion_info {
uint8_t start_symbol; // 0 - 13 (14 symbols in a slot)
uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8)
uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz)
uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern)
uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs
uint8_t nb_mapped_ssb;
uint16_t format; // RO preamble format
} prach_occasion_info_t;
// PRACH occasion slot details
// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency
typedef struct prach_occasion_slot {
prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot
uint8_t nb_of_prach_occasion_in_time;
uint8_t nb_of_prach_occasion_in_freq;
} prach_occasion_slot_t;
// ========================================
typedef enum {
NR_DL_DCI_FORMAT_1_0 = 0,
NR_DL_DCI_FORMAT_1_1,
@@ -133,6 +163,10 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco
int get_format0(uint8_t index, uint8_t unpaired);
int64_t *get_prach_config_info(uint32_t pointa,
uint8_t index,
uint8_t unpaired);
uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config);
int get_num_dmrs(uint16_t dmrs_mask );
+6 -3
View File
@@ -204,7 +204,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
uint16_t band;
int32_t offset;
get_band((cfg->carrier_config.dl_frequency)*1000,
get_band((uint64_t)(cfg->carrier_config.dl_frequency)*1000,
&band,
&offset,
&frame_type);
@@ -243,8 +243,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0;
cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0;
for (i=0; i<4; i++) {
cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
}
break;
default:
@@ -433,6 +433,9 @@ int nr_rrc_mac_config_req_ue(
LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti);
}
// Setup the SSB to Rach Occasions mapping according to the config
build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type);
/*
if(mac_cell_group_configP != NULL){
if(mac_cell_group_configP->drx_Config != NULL ){
+6 -1
View File
@@ -63,7 +63,11 @@
#include "NR_PhysicalCellGroupConfig.h"
#include "NR_CellGroupConfig.h"
#include "NR_ServingCellConfig.h"
#include "NR_MeasConfig.h"
#include "fapi_nr_ue_interface.h"
#include "NR_IF_Module.h"
#include "PHY/defs_nr_common.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h"
#define NB_NR_UE_MAC_INST 1
/*!\brief Maximum number of logical channl group IDs */
@@ -158,6 +162,7 @@ typedef struct {
NR_CellGroupConfig_t *scg;
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated;
int servCellIndex;
NR_CSI_ReportConfig_t *csirc;
//// MAC config
NR_DRX_Config_t *drx_Config;
NR_SchedulingRequestConfig_t *schedulingRequestConfig;
+5 -2
View File
@@ -267,6 +267,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4
@param nr_tti_tx slot for PRACH transmission
@returns indication to generate PRACH to phy */
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id,
int CC_id,
UE_MODE_t UE_mode,
@@ -278,15 +279,14 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
@param module_idP Index of UE instance
@param CC_id Component Carrier Index
@param gNB_index gNB index
@param t_id
@param rach_ConfigDedicated
@returns void */
void nr_get_prach_resources(module_id_t mod_id,
int CC_id,
uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated);
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id);
@@ -305,5 +305,8 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
uint8_t *nb_dmrs_re_per_rb,
uint16_t *number_dmrs_symbols);
void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired);
#endif
/** @}*/
+88 -27
View File
@@ -75,9 +75,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
void nr_get_prach_resources(module_id_t mod_id,
int CC_id,
uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
@@ -87,8 +87,8 @@ void nr_get_prach_resources(module_id_t mod_id,
// NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo
int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0;
uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size;
int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0;
uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size;
AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id);
nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
@@ -100,6 +100,7 @@ void nr_get_prach_resources(module_id_t mod_id,
//////////* UE Random Access Resource Selection *//////////
///////////////////////////////////////////////////////////
// todo:
// - switch initialisation cases
// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
@@ -129,12 +130,81 @@ void nr_get_prach_resources(module_id_t mod_id,
// rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
// Determine the SSB to RACH mapping ratio
// =======================================
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
long cb_preambles_per_ssb; // Nb of preambles per SSB
int total_preambles_per_ssb;
int starting_preamble_nb = 0;
uint8_t ssb_nb_in_ro;
switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 1;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 16;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
break;
default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
break;
}
Msg3_size = mac->RA_Msg3_size;
numberOfRA_Preambles = 64;
if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
// Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration
if ((true == multiple_ssb_per_ro) &&
(ssb_rach_ratio > 1)) {
total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio;
ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro;
starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
}
else {
total_preambles_per_ssb = numberOfRA_Preambles;
starting_preamble_nb = 0;
}
if (!nr_rach_ConfigCommon->groupBconfigured) {
noGroupB = 1;
} else {
@@ -220,29 +290,30 @@ void nr_get_prach_resources(module_id_t mod_id,
if (first_Msg3 == 1) {
if (noGroupB == 1) {
// use Group A preamble
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
mac->RA_usedGroupA = 1;
} else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) {
// Group B is configured and RA preamble Group A is used
// - todo add condition on CCCH_sdu_size for initiation by CCCH
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
mac->RA_usedGroupA = 1;
} else {
// Group B preamble is configured and used
// the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A
// the remaining belong to RA Preambles Group B
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
mac->RA_usedGroupA = 0;
}
} else { // Msg3 is being retransmitted
if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
} else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
} else {
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
}
}
LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex);
}
@@ -268,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id,
// 1) this does not apply to contention-free RA Preamble for beam failure recovery request
// 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario)
prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex;
// ra_RNTI computation
// - todo: this is for TDD FR1 only
// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier
// - f_id: index of the PRACH occasion in the frequency domain
// - s_id is starting symbol of the PRACH occasion [0...14]
// - t_id is the first slot of the PRACH occasion in a system frame [0...80]
ul_carrier_id = 0; // NUL
f_id = rach_ConfigGeneric->msg1_FrequencyStart;
SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4];
s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5];
f_id = prach_pdu->num_ra;
t_id = prach_pdu->prach_slot;
s_id = prach_pdu->prach_start_symbol;
// Pick the first slot of the PRACH occasion in a system frame
for (i = 0; i < 10; i++){
if (((SFN_nbr & (1 << i)) >> i) == 1){
t_id = 2*i;
break;
}
}
prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
mac->ra_rnti = prach_resources->ra_RNTI;
@@ -335,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint
// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id,
int CC_id,
UE_MODE_t UE_mode,
@@ -363,7 +424,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");
if (UE_mode < PUSCH && prach_resources->init_msg1) {
if (prach_resources->init_msg1) {
LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
@@ -449,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated);
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
(uint8_t *) payload, // UL MAC pdu pointer
@@ -576,7 +637,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
} else {
@@ -590,7 +651,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
}
}
@@ -54,13 +54,15 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd
LOG_D(MAC,"Filling search candidates for DCI\n");
rel15->number_of_candidates=3;
rel15->number_of_candidates=4;
rel15->CCE[0]=0;
rel15->L[0]=4;
rel15->CCE[1]=4;
rel15->L[1]=4;
rel15->CCE[2]=8;
rel15->L[2]=4;
rel15->CCE[3]=12;
rel15->L[3]=4;
}
@@ -69,7 +71,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t
uint16_t monitoringSymbolsWithinSlot = 0;
uint8_t bwp_id = 1, coreset_id = 1;
int sps = 0;
def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t));
def_dci_pdu_rel15 = calloc(1,2*sizeof(dci_pdu_rel15_t));
AssertFatal(mac->scc != NULL, "scc is null\n");
NR_ServingCellConfigCommon_t *scc = mac->scc;
NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common;
@@ -121,7 +123,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t
rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275);
rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing;
for (int i = 0; i < rel15->num_dci_options; i++) {
rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format_options[i], NR_RNTI_C, rel15->BWPSize, bwp_id);
rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15+i, rel15->dci_format_options[i], NR_RNTI_C, rel15->BWPSize, bwp_id);
}
break;
case NR_RNTI_RA:
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -274,15 +274,22 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
if (ue_mac->RA_RAPID_found) {
uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc;
unsigned char tpc_command, csi_req;
unsigned char tpc_command;
#ifdef DEBUG_RAR
unsigned char csi_req;
#endif
// TC-RNTI
*t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
ue_mac->t_crnti = *t_crnti;
// TA command
ta_command = rar->TA2 + (rar->TA1 << 5);
#ifdef DEBUG_RAR
// CSI
csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
#endif
// TPC
tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07);
switch (tpc_command){
+15 -7
View File
@@ -128,7 +128,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
uint16_t band;
int32_t offset;
get_band((cfg->carrier_config.dl_frequency.value)*1000,
get_band(((uint64_t)cfg->carrier_config.dl_frequency.value)*1000,
&band,
&offset,
&frame_type);
@@ -329,6 +329,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
}
int rrc_mac_config_req_gNB(module_id_t Mod_idP,
int ssb_SubcarrierOffset,
int pdsch_AntennaPorts,
@@ -381,6 +382,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
if (add_ue == 1 && get_softmodem_params()->phy_test) {
const int UE_id = add_new_nr_ue(Mod_idP,rnti);
UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup;
compute_csi_bitlen (secondaryCellGroup, UE_info, UE_id);
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList =
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
AssertFatal(bwpList->list.count == 1,
@@ -395,12 +397,18 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
NR_RA_t *ra = &RC.nrmac[Mod_idP]->common_channels[CC_id].ra[0];
ra->state = RA_IDLE;
ra->secondaryCellGroup = secondaryCellGroup;
ra->crnti = rnti;
uint8_t num_preamble = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list.count;
ra->preambles.num_preambles = num_preamble;
ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
for (int i = 0; i < num_preamble; i++)
ra->preambles.preamble_list[i] = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex;
if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) {
if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) {
ra->cfra = true;
ra->rnti = rnti;
struct NR_CFRA cfra = *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
uint8_t num_preamble = cfra.resources.choice.ssb->ssb_ResourceList.list.count;
ra->preambles.num_preambles = num_preamble;
ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
for (int i = 0; i < num_preamble; i++)
ra->preambles.preamble_list[i] = cfra.resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex;
}
}
LOG_I(PHY,"Added new RA process for UE RNTI %04x with initial secondaryCellGroup\n", rnti);
} else { // secondaryCellGroup has been updated
const int UE_id = find_nr_UE_id(Mod_idP,rnti);
+87 -62
View File
@@ -344,9 +344,8 @@ void nr_schedule_pucch(int Mod_idP,
frame_t frameP,
sub_frame_t slotP) {
uint16_t O_uci;
uint16_t O_ack;
uint8_t SR_flag = 0; // no SR in PUCCH implemented for now
uint16_t O_csi, O_ack, O_uci;
uint8_t O_sr = 0; // no SR in PUCCH implemented for now
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id);
@@ -359,31 +358,36 @@ void nr_schedule_pucch(int Mod_idP,
NR_sched_pucch *curr_pucch;
for (int k=0; k<nr_ulmix_slots; k++) {
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k];
if ((curr_pucch->dai_c > 0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
UL_tti_req->SFN = curr_pucch->frame;
UL_tti_req->Slot = curr_pucch->ul_slot;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
UL_tti_req->n_pdus+=1;
for (int l=0; l<2; l++) {
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
O_ack = curr_pucch->dai_c;
O_uci = O_ack; // for now we are just sending acknacks in pucch
O_csi = curr_pucch->csi_bits;
O_uci = O_ack + O_csi + O_sr;
if ((O_uci>0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
UL_tti_req->SFN = curr_pucch->frame;
UL_tti_req->Slot = curr_pucch->ul_slot;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
UL_tti_req->n_pdus+=1;
LOG_D(MAC, "Scheduling pucch reception for frame %d slot %d\n", frameP, slotP);
LOG_I(MAC,"Scheduling pucch reception for frame %d slot %d with (%d, %d, %d) (SR ACK, CSI) bits\n",
frameP,slotP,O_sr,O_ack,curr_pucch->csi_bits);
nr_configure_pucch(pucch_pdu,
scc,
ubwp,
curr_pucch->resource_indicator,
O_uci,
O_ack,
SR_flag);
nr_configure_pucch(pucch_pdu,
scc,
ubwp,
UE_info->rnti[UE_id],
curr_pucch->resource_indicator,
O_csi,
O_ack,
O_sr);
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k],
0,
sizeof(NR_sched_pucch));
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
0,
sizeof(NR_sched_pucch));
}
}
}
}
@@ -395,9 +399,12 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
frame_t frame,
sub_frame_t slot){
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP);
int nb_periods_per_frame;
const int UE_id = 0;
const int bwp_id = 1;
@@ -406,24 +413,49 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
NR_COMMON_channels_t *cc = gNB->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
const int num_slots_per_tdd = slots_per_frame[*scc->ssbSubcarrierSpacing] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity);
const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
if (slot == 0 && UE_info->active[UE_id]) {
for (int k=0; k<nr_ulmix_slots; k++) {
/* Seems to be covered 384? */
/*memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k],
0,
sizeof(NR_sched_pucch));*/
/* Seems to be covered in line 335? */
/*memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k],
0,
sizeof(NR_sched_pusch));*/
}
switch(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) {
case 0:
nb_periods_per_frame = 20; // 10ms/0p5ms
break;
case 1:
nb_periods_per_frame = 16; // 10ms/0p625ms
break;
case 2:
nb_periods_per_frame = 10; // 10ms/1ms
break;
case 3:
nb_periods_per_frame = 8; // 10ms/1p25ms
break;
case 4:
nb_periods_per_frame = 5; // 10ms/2ms
break;
case 5:
nb_periods_per_frame = 4; // 10ms/2p5ms
break;
case 6:
nb_periods_per_frame = 2; // 10ms/5ms
break;
case 7:
nb_periods_per_frame = 1; // 10ms/10ms
break;
default:
AssertFatal(1==0,"Undefined tdd period %d\n", scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
}
int num_slots_per_tdd = (slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame;
const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
@@ -435,27 +467,29 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
}
const uint64_t dlsch_in_slot_bitmap = (1 << 1);
const uint64_t dlsch_in_slot_bitmap = (1 << 1) | (1 << 2);
const uint64_t ulsch_in_slot_bitmap = (1 << 8);
memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
for (int i=0; i<MAX_NUM_CORESET; i++)
RC.nrmac[module_idP]->UE_info.num_pdcch_cand[UE_id][i] = 0;
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
//mbsfn_status[CC_id] = 0;
// clear vrb_maps
memset(cc[CC_id].vrb_map, 0, 275);
memset(cc[CC_id].vrb_map_UL, 0, 275);
memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * 275);
memset(cc[CC_id].vrb_map_UL, 0, sizeof(uint16_t) * 275);
clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot);
}
if ((slot == 0) && (frame & 127) == 0) dump_mac_stats(RC.nrmac[module_idP]);
// This schedules MIB
if((slot == 0) && (frame & 7) == 0){
schedule_nr_mib(module_idP, frame, slot);
}
schedule_nr_mib(module_idP, frame, slot, slots_per_frame[*scc->ssbSubcarrierSpacing]);
// This schedule PRACH if we are not in phy_test mode
if (get_softmodem_params()->phy_test == 0)
@@ -464,49 +498,40 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
// This schedule SR
// TODO
// This schedule CSI
// TODO
// This schedule CSI measurement reporting
if (UE_info->active[UE_id])
nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, slots_per_frame[*scc->ssbSubcarrierSpacing]);
// This schedule RA procedure if not in phy_test mode
// Otherwise already consider 5G already connected
RC.nrmac[module_idP]->current_slot=slot;
if (get_softmodem_params()->phy_test == 0) {
nr_schedule_RA(module_idP, frame, slot);
nr_schedule_reception_msg3(module_idP, 0, frame, slot);
}
if (UE_info->active[UE_id]) {
// TbD once RACH is available, start ta_timer when UE is connected
if (ue_sched_ctl->ta_timer)
ue_sched_ctl->ta_timer--;
if (ue_sched_ctl->ta_timer == 0) {
ue_sched_ctl->ta_apply = true;
/* if time is up, then set the timer to not send it for 5 frames
// regardless of the TA value */
ue_sched_ctl->ta_timer = 100;
}
}
// This schedules the DCI for Uplink and subsequently PUSCH
// The decision about whether to schedule is done for each UE independently
// inside
if (UE_info->active[UE_id] && slot < 10) {
int tda = 1; // time domain assignment hardcoded for now
schedule_fapi_ul_pdu(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, tda, ulsch_in_slot_bitmap);
nr_schedule_pusch(module_idP, UE_id, num_slots_per_tdd, nr_ulmix_slots, frame, slot);
}
if (UE_info->active[UE_id]
&& (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd))
&& (!get_softmodem_params()->phy_test || slot == 1)
&& slot < 10) {
ue_sched_ctl->current_harq_pid = slot % num_slots_per_tdd;
//int pucch_sched;
//nr_update_pucch_scheduling(module_idP, UE_id, frame, slot, num_slots_per_tdd,&pucch_sched);
//nr_schedule_uss_dlsch_phytest(module_idP, frame, slot, &UE_info->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL);
nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd);
ue_sched_ctl->ta_apply = false;
}
if (UE_info->active[UE_id])
nr_schedule_pucch(module_idP, UE_id, nr_ulmix_slots, frame, slot);
+24 -18
View File
@@ -451,9 +451,11 @@ void nr_initiate_ra_proc(module_id_t module_idP,
break;
}
}
if (!pr_found) {
LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
module_idP, preamble_index);
return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
}
// This should be handled differently when we use the initialBWP for RA
@@ -499,17 +501,17 @@ void nr_initiate_ra_proc(module_id_t module_idP,
ra->Msg2_slot = msg2_slot;
LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
if(pr_found)
do {
ra->rnti = (taus() % 65518) + 1;
loop++;
if (!ra->cfra) {
do {
ra->rnti = (taus() % 65518) + 1;
loop++;
}
while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519));
if (loop == 100) {
LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
abort();
}
}
while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519));
if (loop == 100) {
LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
abort();
}
ra->RA_rnti = ra_rnti;
ra->preamble_index = preamble_index;
ra->beam_id = beam_index;
@@ -881,13 +883,13 @@ void nr_generate_Msg2(module_id_t module_idP,
uint8_t nr_of_candidates, aggregation_level;
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
int CCEIndex = allocate_nr_CCEs(
nr_mac,
bwp,
coreset,
aggregation_level,
0, /* n_RNTI 0: common search space */
0); // m
int CCEIndex = allocate_nr_CCEs(nr_mac,
bwp,
coreset,
aggregation_level,
0, // Y
0, // m
nr_of_candidates);
if (CCEIndex < 0) {
LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
@@ -940,8 +942,12 @@ void nr_generate_Msg2(module_id_t module_idP,
nr_mac->TX_req[CC_id].Slot = slotP;
memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length);
T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id),
T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */,
T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length));
/* mark the corresponding RBs as used */
uint8_t *vrb_map = cc[CC_id].vrb_map;
uint16_t *vrb_map = cc[CC_id].vrb_map;
for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++)
vrb_map[rb + pdsch_pdu_rel15->rbStart] = 1;
}
+136 -82
View File
@@ -56,7 +56,7 @@
extern RAN_CONTEXT_t RC;
extern uint8_t SSB_Table[38];
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, uint8_t slots_per_frame){
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
NR_COMMON_channels_t *cc;
@@ -69,98 +69,152 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
int CC_id;
uint8_t beam_index = 0;
AssertFatal(slotP == 0, "Subframe must be 0\n");
AssertFatal((frameP & 7) == 0, "Frame must be a multiple of 8\n");
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
dl_tti_request = &gNB->DL_req[CC_id];
dl_req = &dl_tti_request->dl_tti_request_body;
cc = &gNB->common_channels[CC_id];
#if 0
//SSB is transmitted based on SSB periodicity
if((frameP % cfg->ssb_table.ssb_period.value) == 0) {
uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
uint32_t ssb_index = -1;
for (int i=0; i<2; i++) { // max two SSB per slot
ssb_index = i + SSB_Table[slotP]; // computing the ssb_index
if ((ssb_index<64) && ((L_ssb >> (63-ssb_index)) & 0x01)) { // generating the ssb only if the bit of L_ssb at current ssb index is 1
#endif
const long band = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
const uint32_t ssb_offset0 = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
int ratio;
switch (*cc->ServingCellConfigCommon->ssbSubcarrierSpacing) {
case NR_SubcarrierSpacing_kHz15:
AssertFatal(band <= 79,
"Band %ld is not possible for SSB with 15 kHz SCS\n",
band);
if (band < 77) // below 3GHz
ratio = 3; // NRARFCN step is 5 kHz
else
ratio = 1; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz30:
AssertFatal(band <= 79,
"Band %ld is not possible for SSB with 15 kHz SCS\n",
band);
if (band < 77) // below 3GHz
ratio = 6; // NRARFCN step is 5 kHz
else
ratio = 2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz120:
AssertFatal(band >= 257,
"Band %ld is not possible for SSB with 120 kHz SCS\n",
band);
ratio = 2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz240:
AssertFatal(band >= 257,
"Band %ld is not possible for SSB with 240 kHz SCS\n",
band);
ratio = 4; // NRARFCN step is 15 kHz
break;
default:
AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n",
*cc->ServingCellConfigCommon->ssbSubcarrierSpacing);
}
mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0]); // not used in this case
// scheduling MIB every 8 frames, PHY repeats it in between
if((slotP == 0) && (frameP & 7) == 0) {
dl_tti_request = &gNB->DL_req[CC_id];
dl_req = &dl_tti_request->dl_tti_request_body;
LOG_D(MAC, "Frame %d, slot %d: BCH PDU length %d\n", frameP, slotP, mib_sdu_length);
mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0]);
if (mib_sdu_length > 0) {
LOG_D(MAC, "Frame %d, slot %d: BCH PDU length %d\n", frameP, slotP, mib_sdu_length);
LOG_D(MAC, "Frame %d, slot %d: Adding BCH PDU in position %d (length %d)\n", frameP, slotP, dl_req->nPDUs, mib_sdu_length);
if (mib_sdu_length > 0) {
LOG_D(MAC,
"Frame %d, slot %d: Adding BCH PDU in position %d (length %d)\n",
frameP,
slotP,
dl_req->nPDUs,
mib_sdu_length);
if ((frameP & 1023) < 80){
LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length);
if ((frameP & 1023) < 80){
LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length);
}
dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_config_pdu->PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE;
dl_config_pdu->PDUSize =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t);
AssertFatal(cc->ServingCellConfigCommon->physCellId!=NULL,"cc->ServingCellConfigCommon->physCellId is null\n");
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *cc->ServingCellConfigCommon->physCellId;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n",cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count);
AssertFatal(cc->ServingCellConfigCommon->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n");
const nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; //kSSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10; // absoluteFrequencySSB is the center of SSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1);
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs=1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size=275; //1 PRG of max size for analogue beamforming
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces=1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
dl_req->nPDUs++;
}
}
dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_config_pdu->PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE;
dl_config_pdu->PDUSize =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t);
AssertFatal(cc->ServingCellConfigCommon->physCellId!=NULL,"cc->ServingCellConfigCommon->physCellId is null\n");
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *cc->ServingCellConfigCommon->physCellId;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;//ssb_index ;//SSB index for each SSB
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n",cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count);
AssertFatal(cc->ServingCellConfigCommon->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n");
long band = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
uint32_t ssb_offset0 = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
int ratio;
switch (*cc->ServingCellConfigCommon->ssbSubcarrierSpacing) {
case NR_SubcarrierSpacing_kHz15:
AssertFatal(band <= 79, "Band %ld is not possible for SSB with 15 kHz SCS\n",band);
if (band<77) // below 3GHz
ratio=3; // NRARFCN step is 5 kHz
else
ratio=1; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz30:
AssertFatal(band <= 79, "Band %ld is not possible for SSB with 15 kHz SCS\n",band);
if (band<77) // below 3GHz
ratio=6; // NRARFCN step is 5 kHz
else
ratio=2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz120:
AssertFatal(band >= 257, "Band %ld is not possible for SSB with 120 kHz SCS\n",band);
ratio=2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz240:
AssertFatal(band >= 257, "Band %ld is not possible for SSB with 240 kHz SCS\n",band);
ratio=4; // NRARFCN step is 15 kHz
break;
default:
AssertFatal(1==0,"SCS %ld not allowed for SSB \n", *cc->ServingCellConfigCommon->ssbSubcarrierSpacing);
}
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; //kSSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10;/*cfg->ssb_table.ssb_offset_point_a.value;*/ // absoluteFrequencySSB is the center of SSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1);
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs=1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size=275; //1 PRG of max size for analogue beamforming
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces=1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
dl_req->nPDUs++;
uint8_t *vrb_map = cc[CC_id].vrb_map;
const int rbStart = dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA;
for (int rb = 0; rb < 20; rb++)
vrb_map[rbStart + rb] = 1;
// checking if there is any SSB in slot
const int abs_slot = (slots_per_frame * frameP) + slotP;
const int slot_per_period = (slots_per_frame>>1)<<(*cc->ServingCellConfigCommon->ssb_periodicityServingCell);
int eff_120_slot;
const BIT_STRING_t *mediumBitmap = &cc->ServingCellConfigCommon->ssb_PositionsInBurst->choice.mediumBitmap;
uint8_t buf = 0;
switch (cc->ServingCellConfigCommon->ssb_PositionsInBurst->present) {
case 1:
// presence of ssbs possible in the first 2 slots of ssb period
if ((abs_slot % slot_per_period) < 2 &&
(((mediumBitmap->buf[0]) >> (6 - (slotP << 1))) & 3) != 0)
fill_ssb_vrb_map(cc, (ssb_offset0 / (ratio * 12) - 10), CC_id);
break;
case 2:
// presence of ssbs possible in the first 4 slots of ssb period
if ((abs_slot % slot_per_period) < 4 &&
(((mediumBitmap->buf[0]) >> (6 - (slotP << 1))) & 3) != 0)
fill_ssb_vrb_map(cc, (ssb_offset0 / (ratio * 12) - 10), CC_id);
break;
case 3:
AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing ==
NR_SubcarrierSpacing_kHz120,
"240kHZ subcarrier spacing currently not supported for SSBs\n");
if ((abs_slot % slot_per_period) < 8) {
eff_120_slot = slotP;
buf = mediumBitmap->buf[0];
} else if ((abs_slot % slot_per_period) < 17) {
eff_120_slot = slotP - 9;
buf = mediumBitmap->buf[1];
} else if ((abs_slot % slot_per_period) < 26) {
eff_120_slot = slotP - 18;
buf = mediumBitmap->buf[2];
} else if ((abs_slot % slot_per_period) < 35) {
eff_120_slot = slotP - 27;
buf = mediumBitmap->buf[3];
}
if (((buf >> (6 - (eff_120_slot << 1))) & 3) != 0)
fill_ssb_vrb_map(cc, ssb_offset0 / (ratio * 12) - 10, CC_id);
break;
default:
AssertFatal(0,
"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
cc->ServingCellConfigCommon->ssb_PositionsInBurst->present);
}
}
}
void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
//----------------------------------------
}
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int CC_id) {
uint16_t *vrb_map = cc[CC_id].vrb_map;
for (int rb = 0; rb < 20; rb++)
vrb_map[rbStart + rb] = 1;
}
+139 -89
View File
@@ -343,68 +343,98 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
return offset;
}
void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10) {
void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch,
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234,
NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) {
// TODO
int max_harq_rounds = 4; // TODO define macro
int num_ucis = UL_info->uci_ind.num_ucis;
nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list;
for (int i = 0; i < num_ucis; i++) {
switch (uci_list[i].pdu_type) {
case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break;
if (uci_01 != NULL) {
// handle harq
int harq_idx_s = 0;
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
//if (get_softmodem_params()->phy_test == 0) {
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1;
// handle harq
int harq_idx_s = 0;
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30);
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_pdu->harq->num_harq; harq_bit++) {
// search for the right harq process
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
// if the gNB received ack with a good confidence
if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
if ((uci_pdu->harq->harq_list[harq_bit].harq_value == 1) &&
(uci_pdu->harq->harq_confidence_level == 0)) {
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
stats->dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
(sched_ctrl->harq_processes[harq_idx].is_waiting)) {
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
// search for the right harq process
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
// if the gNB received ack with a good confidence
if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) &&
(uci_01->harq->harq_confidence_level == 0)) {
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
//}
break;
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
stats->dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
(sched_ctrl->harq_processes[harq_idx].is_waiting)) {
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break;
}
}
UL_info->uci_ind.num_ucis = 0;
if (uci_234 != NULL) {
int harq_idx_s = 0;
int acknack;
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01;
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) {
// if the gNB received ack with a good confidence or if the max harq rounds was reached
if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
// TODO add some confidence level for when there is no CRC
if ((uci_234->harq.harq_crc != 1) && acknack) {
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
stats->dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
(sched_ctrl->harq_processes[harq_idx].is_waiting)) {
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
}
}
}
int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) {
@@ -453,7 +483,6 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
const int CC_id = 0;
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
sched_ctrl->rbSize = 0;
/* Retrieve amount of data to send for this UE */
sched_ctrl->num_total_bytes = 0;
@@ -470,7 +499,8 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
0,
0);
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
if (sched_ctrl->num_total_bytes == 0 && !get_softmodem_params()->phy_test)
if (sched_ctrl->num_total_bytes == 0
&& !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
return;
LOG_D(MAC,
"%d.%d, DTCH%d->DLSCH, RLC status %d bytes\n",
@@ -488,23 +518,34 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
sched_ctrl->search_space);
sched_ctrl->coreset = get_coreset(
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
int cid = sched_ctrl->coreset->controlResourceSetId;
const uint16_t Y = UE_info->Y[UE_id][cid][slot];
const int m = UE_info->num_pdcch_cand[UE_id][cid];
sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
sched_ctrl->active_bwp,
sched_ctrl->coreset,
sched_ctrl->aggregation_level,
UE_info->rnti[UE_id],
0); // m
sched_ctrl->active_bwp,
sched_ctrl->coreset,
sched_ctrl->aggregation_level,
Y,
m,
nr_of_candidates);
if (sched_ctrl->cce_index < 0) {
LOG_E(MAC, "%s(): could not find CCE for UE %d\n", __func__, UE_id);
return;
}
UE_info->num_pdcch_cand[UE_id][cid]++;
/* Find PUCCH occasion */
nr_update_pucch_scheduling(
module_id, UE_id, frame, slot, num_slots_per_tdd, &sched_ctrl->pucch_sched_idx);
nr_acknack_scheduling(module_id,
UE_id,
frame,
slot,
num_slots_per_tdd,
&sched_ctrl->pucch_sched_idx,
&sched_ctrl->pucch_occ_idx);
AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
uint8_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
const int current_harq_pid = sched_ctrl->current_harq_pid;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
@@ -584,18 +625,26 @@ void nr_schedule_ue_spec(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd) {
/* PREPROCESSOR */
nr_simple_dlsch_preprocessor(module_id, frame, slot, num_slots_per_tdd);
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
/* PREPROCESSOR */
gNB_mac->pre_processor_dl(module_id, frame, slot, num_slots_per_tdd);
NR_UE_info_t *UE_info = &gNB_mac->UE_info;
const int CC_id = 0;
NR_UE_list_t *UE_list = &UE_info->list;
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
if (sched_ctrl->rbSize <= 0 && !get_softmodem_params()->phy_test)
/* update TA and set ta_apply every 10 frames.
* Possible improvement: take the periodicity from input file.
* If such UE is not scheduled now, it will be by the preprocessor later.
* If we add the CE, ta_apply will be reset */
if (frame >= (sched_ctrl->ta_frame + 10) % 1023)
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
if (sched_ctrl->rbSize <= 0)
continue;
const rnti_t rnti = UE_info->rnti[UE_id];
@@ -629,34 +678,24 @@ void nr_schedule_ue_spec(module_id_t module_id,
const int current_harq_pid = sched_ctrl->current_harq_pid;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx];
NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx][sched_ctrl->pucch_occ_idx];
harq->feedback_slot = pucch->ul_slot;
harq->is_waiting = 1;
UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
nr_fill_nfapi_dl_pdu(module_id,
UE_id,
sched_ctrl->active_bwp->bwp_Id,
sched_ctrl->search_space,
sched_ctrl->coreset,
dl_req,
rnti,
UE_info->secondaryCellGroup[UE_id],
sched_ctrl,
pucch,
1 /* nrOfLayers */,
sched_ctrl->mcs,
sched_ctrl->rbSize,
sched_ctrl->rbStart,
sched_ctrl->numDmrsCdmGrpsNoData,
getDmrsConfigType(sched_ctrl->active_bwp),
sched_ctrl->mcsTableIdx,
nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
TBS,
sched_ctrl->time_domain_allocation,
startSymbolIndex,
nrOfSymbols,
sched_ctrl->aggregation_level,
sched_ctrl->cce_index,
current_harq_pid,
harq->ndi,
harq->round);
@@ -693,7 +732,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
* nr_generate_dlsch_pdu() checks for ta_apply and add TA CE if necessary */
const int ta_len = (sched_ctrl->ta_apply) ? 2 : 0;
/* Get RLC data TODO: remove random data retrieval */
/* Get RLC data */
int header_length_total = 0;
int header_length_last = 0;
int sdu_length_total = 0;
@@ -735,10 +774,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
sdu_length_total += sdu_lengths[num_sdus];
header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128);
header_length_total += header_length_last;
num_sdus++;
//ue_sched_ctl->uplane_inactivity_timer = 0;
}
else if (get_softmodem_params()->phy_test) {
LOG_D(MAC, "Configuring DL_TX in %d.%d: random data\n", frame, slot);
@@ -755,10 +791,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total;
// Check if there is data from RLC or CE
const int post_padding = TBS >= 2 + header_length_total + sdu_length_total + ta_len;
// padding param currently not in use
//padding = TBS - header_length_total - sdu_length_total - ta_len - 1;
const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
@@ -799,6 +832,20 @@ void nr_schedule_ue_spec(module_id_t module_id,
retInfo->mcs = sched_ctrl->mcs;
retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
// ta command is sent, values are reset
if (sched_ctrl->ta_apply) {
sched_ctrl->ta_apply = false;
sched_ctrl->ta_frame = frame;
LOG_D(MAC,
"%d.%2d UE %d TA scheduled, resetting TA frame\n",
frame,
slot,
UE_id);
}
T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(buf, TBS));
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frame%100 == 0) {
LOG_I(MAC,
@@ -811,5 +858,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
}
#endif
}
/* mark UE as scheduled */
sched_ctrl->rbSize = 0;
}
}
+105 -456
View File
@@ -252,235 +252,104 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
}
}
int configure_fapi_dl_pdu_phytest(int Mod_idP,
nfapi_nr_dl_tti_request_body_t *dl_req,
NR_sched_pucch *pucch_sched,
uint8_t *mcsIndex,
uint16_t *rbSize,
uint16_t *rbStart) {
gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP];
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
/* schedules whole bandwidth for first user, all the time */
void nr_preprocessor_phytest(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd)
{
if (slot != 1)
return; /* only schedule in slot 1 for now */
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
const int UE_id = 0;
const int CC_id = 0;
AssertFatal(UE_info->active[UE_id],
"%s(): expected UE %d to be active\n",
__func__,
UE_id);
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu;
int TBS;
int bwp_id=1;
int UE_id = 0;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1];
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n");
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0,
"searchPsacesToAddModList is empty\n");
dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
pdsch_pdu_rel15->pduBitmap = 0;
pdsch_pdu_rel15->rnti = UE_info->rnti[UE_id];
pdsch_pdu_rel15->pduIndex = 0;
// BWP
pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
if (bwp->bwp_Common->genericParameters.cyclicPrefix) pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix;
else pdsch_pdu_rel15->CyclicPrefix=0;
pdsch_pdu_rel15->NrOfCodewords = 1;
int mcs = (mcsIndex!=NULL) ? *mcsIndex : 9;
int current_harq_pid = UE_info->UE_sched_ctrl[UE_id].current_harq_pid;
pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs,0);
pdsch_pdu_rel15->qamModOrder[0] = 2;
pdsch_pdu_rel15->mcsIndex[0] = mcs;
pdsch_pdu_rel15->mcsTable[0] = 0;
pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round];
pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
pdsch_pdu_rel15->nrOfLayers = 1;
pdsch_pdu_rel15->transmissionScheme = 0;
pdsch_pdu_rel15->refPoint = 0; // Point A
UE_info->mac_stats[UE_id].dlsch_rounds[UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round]++;
pdsch_pdu_rel15->dmrsConfigType = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
pdsch_pdu_rel15->SCID = 0;
pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 1;
pdsch_pdu_rel15->dmrsPorts = 1;
pdsch_pdu_rel15->resourceAlloc = 1;
pdsch_pdu_rel15->rbStart = (rbStart!=NULL) ? *rbStart : 0;
pdsch_pdu_rel15->rbSize = (rbSize!=NULL) ? *rbSize : pdsch_pdu_rel15->BWPSize;
pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
int startSymbolAndLength=0;
int time_domain_assignment=2;
int StartSymbolIndex,NrOfSymbols;
AssertFatal(time_domain_assignment<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count,"time_domain_assignment %d>=%d\n",time_domain_assignment,bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count);
startSymbolAndLength = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength;
SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols);
pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
// k0 = *bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0;
pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
scc->dmrs_TypeA_Position,
pdsch_pdu_rel15->NrOfSymbols);
dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t));
// bwp indicator
int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count;
if (n_dl_bwp < 4)
dci_pdu_rel15[0].bwp_indicator.val = bwp_id;
else
dci_pdu_rel15[0].bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212
// frequency domain assignment
if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation==NR_PDSCH_Config__resourceAllocation_resourceAllocationType1)
dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
pdsch_pdu_rel15->rbStart,
NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275));
else
AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n");
// time domain assignment
dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV;
// mcs and rv
dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0];
dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
// harq pid and ndi
dci_pdu_rel15[0].harq_pid = current_harq_pid;
dci_pdu_rel15[0].ndi = UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].ndi;
// DAI
dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3;
// TPC for PUCCH
dci_pdu_rel15[0].tpc = UE_info->UE_sched_ctrl[UE_id].tpc1; // table 7.2.1-1 in 38.213
// PUCCH resource indicator
dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator;
// PDSCH to HARQ TI
dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator;
UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].feedback_slot = pucch_sched->ul_slot;
UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].is_waiting = 1;
// antenna ports
dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0
// dmrs sequence initialization
dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
LOG_D(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n",
dci_pdu_rel15[0].frequency_domain_assignment.val,
pdsch_pdu_rel15->rbStart,
pdsch_pdu_rel15->rbSize,
NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275),
dci_pdu_rel15[0].time_domain_assignment.val,
dci_pdu_rel15[0].vrb_to_prb_mapping.val,
dci_pdu_rel15[0].mcs,
dci_pdu_rel15[0].tb_scaling,
dci_pdu_rel15[0].ndi,
dci_pdu_rel15[0].rv);
NR_SearchSpace_t *ss;
int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n");
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0,
"searchPsacesToAddModList is empty\n");
int found=0;
for (int i=0;i<bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) {
ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i];
AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n");
AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n");
if (ss->searchSpaceType->present == target_ss) {
found=1;
break;
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
/* find largest unallocated chunk */
const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
int rbStart = 0;
int tStart = 0;
int rbSize = 0;
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
/* find largest unallocated RB region */
do {
/* advance to first free RB */
while (tStart < bwpSize && vrb_map[tStart])
tStart++;
/* find maximum rbSize at current rbStart */
int tSize = 1;
while (tStart + tSize < bwpSize && !vrb_map[tStart + tSize])
tSize++;
if (tSize > rbSize) {
rbStart = tStart;
rbSize = tSize;
}
}
AssertFatal(found==1,"Couldn't find an adequate searchspace\n");
tStart += tSize;
} while (tStart < bwpSize);
uint8_t nr_of_candidates, aggregation_level;
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 1 /* dedicated */);
int CCEIndex = allocate_nr_CCEs(
nr_mac,
bwp,
coreset,
aggregation_level,
UE_info->rnti[UE_id],
0); // m
if (CCEIndex < 0) {
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PDSCH\n", __func__);
free(dci_pdu_rel15);
return 0;
}
nr_configure_pdcch(nr_mac,
pdcch_pdu_rel15,
UE_info->rnti[UE_id],
ss,
coreset,
scc,
bwp,
aggregation_level,
CCEIndex);
sched_ctrl->num_total_bytes = 0;
const int lcid = DL_SCH_LCID_DTCH;
const uint16_t rnti = UE_info->rnti[UE_id];
/* update sched_ctrl->num_total_bytes so that postprocessor schedules data,
* if available */
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
rnti,
module_id,
frame,
slot,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0,
0);
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
int dci_formats[2];
int rnti_types[2];
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats)
dci_formats[0] = NR_DL_DCI_FORMAT_1_1;
else
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
uint8_t nr_of_candidates;
find_aggregation_candidates(&sched_ctrl->aggregation_level,
&nr_of_candidates,
sched_ctrl->search_space);
sched_ctrl->coreset = get_coreset(
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
const int cid = sched_ctrl->coreset->controlResourceSetId;
const uint16_t Y = UE_info->Y[UE_id][cid][RC.nrmac[module_id]->current_slot];
const int m = UE_info->num_pdcch_cand[UE_id][cid];
sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
sched_ctrl->active_bwp,
sched_ctrl->coreset,
sched_ctrl->aggregation_level,
Y,
m,
nr_of_candidates);
AssertFatal(sched_ctrl->cce_index >= 0,
"%s(): could not find CCE for UE %d\n",
__func__,
UE_id);
rnti_types[0] = NR_RNTI_C;
nr_acknack_scheduling(module_id,
UE_id,
frame,
slot,
num_slots_per_tdd,
&sched_ctrl->pucch_sched_idx,
&sched_ctrl->pucch_occ_idx);
AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id);
sched_ctrl->rbStart = rbStart;
sched_ctrl->rbSize = rbSize;
sched_ctrl->time_domain_allocation = 2;
sched_ctrl->mcsTableIdx = 0;
sched_ctrl->mcs = 9;
sched_ctrl->numDmrsCdmGrpsNoData = 1;
LOG_D(MAC, "DCI params: rnti %x, rnti_type %d, dci_format %d\n \
coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
pdcch_pdu_rel15->dci_pdu.RNTI[0],
rnti_types[0],
dci_formats[0],
(unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
pdcch_pdu_rel15->StartSymbolIndex,
pdcch_pdu_rel15->DurationSymbols);
int x_Overhead = 0; // should be 0 for initialBWP
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu,x_Overhead,pdsch_pdu_rel15->numDmrsCdmGrpsNoData,0);
// Hardcode it for now
TBS = dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15.TBSize[0];
if (UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round==0)
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d startSymbolAndLength %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS: %d\n",
pdsch_pdu_rel15->rbStart,
pdsch_pdu_rel15->rbSize,
startSymbolAndLength,
pdsch_pdu_rel15->StartSymbolIndex,
pdsch_pdu_rel15->NrOfSymbols,
pdsch_pdu_rel15->nrOfLayers,
pdsch_pdu_rel15->NrOfCodewords,
pdsch_pdu_rel15->mcsIndex[0],
TBS);
free(dci_pdu_rel15);
return TBS; //Return TBS in bytes
/* mark the corresponding RBs as used */
for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
vrb_map[rb + sched_ctrl->rbStart] = 1;
}
void config_uldci(NR_BWP_Uplink_t *ubwp,
@@ -559,231 +428,6 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,
}
void configure_fapi_dl_Tx(module_id_t Mod_idP,
frame_t frameP,
sub_frame_t slotP,
nfapi_nr_dl_tti_request_body_t *dl_req,
nfapi_nr_pdu_t *tx_req,
int tbs_bytes,
int16_t pdu_index){
int CC_id = 0;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP];
LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS (bytes): %d\n",
pdsch_pdu_rel15->rbStart,
pdsch_pdu_rel15->rbSize,
pdsch_pdu_rel15->StartSymbolIndex,
pdsch_pdu_rel15->NrOfSymbols,
pdsch_pdu_rel15->nrOfLayers,
pdsch_pdu_rel15->NrOfCodewords,
pdsch_pdu_rel15->mcsIndex[0],
tbs_bytes);
dl_req->nPDUs+=2;
tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
tx_req->PDU_index = nr_mac->pdu_index[0]++;
tx_req->num_TLV = 1;
tx_req->TLVs[0].length = tbs_bytes +2;
memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&nr_mac->UE_info.DLSCH_pdu[0][0].payload[0], tbs_bytes);
nr_mac->TX_req[CC_id].Number_of_PDUs++;
nr_mac->TX_req[CC_id].SFN = frameP;
nr_mac->TX_req[CC_id].Slot = slotP;
}
void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t slotP,
NR_sched_pucch *pucch_sched,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *dlsch_config){
LOG_D(MAC, "In nr_schedule_uss_dlsch_phytest frame %d slot %d\n",frameP,slotP);
int post_padding = 0, header_length_total = 0, sdu_length_total = 0, num_sdus = 0;
int lcid, offset, i, header_length_last, TBS_bytes = 0;
int UE_id = 0, CC_id = 0;
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
//NR_COMMON_channels_t *cc = nr_mac->common_channels;
//NR_ServingCellConfigCommon_t *scc=cc->ServingCellConfigCommon;
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[gNB_mac->TX_req[CC_id].Number_of_PDUs];
mac_rlc_status_resp_t rlc_status;
NR_UE_info_t *UE_info = &gNB_mac->UE_info;
if (UE_info->num_UEs ==0) return;
unsigned char sdu_lcids[NB_RB_MAX] = {0};
uint16_t sdu_lengths[NB_RB_MAX] = {0};
uint16_t rnti = UE_info->rnti[UE_id];
NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
uint8_t mac_sdus[MAX_NR_DLSCH_PAYLOAD_BYTES];
LOG_D(MAC, "Scheduling UE specific search space DCI type 1\n");
int ta_len = (ue_sched_ctl->ta_apply)?2:0;
TBS_bytes = configure_fapi_dl_pdu_phytest(
module_idP,
dl_req,
pucch_sched,
dlsch_config != NULL ? dlsch_config->mcsIndex : NULL,
dlsch_config != NULL ? &dlsch_config->rbSize : NULL,
dlsch_config != NULL ? &dlsch_config->rbStart : NULL);
if (TBS_bytes == 0)
return;
lcid = DL_SCH_LCID_DTCH;
//for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) {
// TODO: check if the lcid is active
LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n",
module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3);
//if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) {
rlc_status = mac_rlc_status_ind(module_idP,
rnti,
module_idP,
frameP,
slotP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0,
0);
if (rlc_status.bytes_in_buffer > 0) {
LOG_I(MAC, "configure fapi due to data availability \n");
LOG_I(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n",
module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3,
lcid, header_length_total, TBS_bytes);
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
rnti,
module_idP,
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
TBS_bytes - ta_len - header_length_total - sdu_length_total - 3,
(char *)&mac_sdus[sdu_length_total],
0,
0);
LOG_W(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid);
sdu_lcids[num_sdus] = lcid;
sdu_length_total += sdu_lengths[num_sdus];
header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128);
header_length_total += header_length_last;
num_sdus++;
//ue_sched_ctl->uplane_inactivity_timer = 0;
}
else {
LOG_D(MAC,"Configuring DL_TX in %d.%d\n", frameP, slotP);
// fill dlsch_buffer with random data
for (i = 0; i < TBS_bytes; i++){
mac_sdus[i] = (unsigned char) (lrand48()&0xff);
//((uint8_t *)gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0])[i] = (unsigned char) (lrand48()&0xff);
}
//Sending SDUs with size 1
//Initialize elements of sdu_lcids and sdu_lengths
sdu_lcids[0] = 0x3f; // DRB
sdu_lengths[0] = TBS_bytes - ta_len - 3;
header_length_total += 2 + (sdu_lengths[0] >= 128);
sdu_length_total += sdu_lengths[0];
num_sdus +=1;
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frameP%100 == 0){
LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes);
for(int i = 0; i < 10; i++) {
LOG_I(MAC, "%x. ", ((uint8_t *)gNB_mac->UE_info.DLSCH_pdu[CC_id][0][0].payload[0])[i]);
}
}
#endif
}
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total;
// there is at least one SDU or TA command
// if (num_sdus > 0 ){
if (ta_len + sdu_length_total + header_length_total > 0) {
// Check if there is data from RLC or CE
if (TBS_bytes >= 2 + header_length_total + sdu_length_total + ta_len) {
// we have to consider padding
// padding param currently not in use
//padding = TBS_bytes - header_length_total - sdu_length_total - ta_len - 1;
post_padding = 1;
} else {
//padding = 0;
post_padding = 0;
}
offset = nr_generate_dlsch_pdu(module_idP,
&UE_info->UE_sched_ctrl[UE_id],
(unsigned char *) mac_sdus,
(unsigned char *) gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0],
num_sdus, //num_sdus
sdu_lengths,
sdu_lcids,
255, // no drx
NULL, // contention res id
post_padding);
// Padding: fill remainder of DLSCH with 0
if (post_padding > 0){
for (int j = 0; j < (TBS_bytes - offset); j++)
gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0][offset + j] = 0; // mac_pdu[offset + j] = 0;
}
configure_fapi_dl_Tx(module_idP, frameP, slotP, dl_req, tx_req, TBS_bytes, gNB_mac->pdu_index[CC_id]);
if(IS_SOFTMODEM_NOS1){
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n \n", frameP, slotP, TBS_bytes);
for(int i = 0; i < 10; i++) { // TBS_bytes dlsch_pdu_rel15->transport_block_size/8 6784/8
LOG_I(MAC, "%x. ", mac_payload[i]);
}
#endif
} else {
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frameP%100 == 0){
LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes);
for(int i = 0; i < 10; i++) {
LOG_I(MAC, "byte %d : %x\n", i,((uint8_t *)gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0])[i]); //LOG_I(MAC, "%x. ", mac_payload[i]);
}
}
#endif
}
}
else { // There is no data from RLC or MAC header, so don't schedule
}
}
int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) {
uint8_t hrq_id;
@@ -864,7 +508,8 @@ void schedule_fapi_ul_pdu(int Mod_idP,
* conditions might exclude each other and never be true */
const int slot_idx = (slotP + K2) % num_slots_per_tdd;
if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot_idx)
&& (!get_softmodem_params()->phy_test || slot_idx == 8)) {
&& (!get_softmodem_params()->phy_test || slot_idx == 8)) {
nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0];
UL_dci_req->SFN = frameP;
UL_dci_req->Slot = slotP;
@@ -974,7 +619,7 @@ void schedule_fapi_ul_pdu(int Mod_idP,
pusch_pdu->resource_alloc = 1; //type 1
pusch_pdu->rb_start = 0;
if (get_softmodem_params()->phy_test==1)
pusch_pdu->rb_size = 50;
pusch_pdu->rb_size = min(pusch_pdu->bwp_size,50);
else
pusch_pdu->rb_size = pusch_pdu->bwp_size;
}
@@ -1126,19 +771,23 @@ void schedule_fapi_ul_pdu(int Mod_idP,
uint8_t nr_of_candidates, aggregation_level;
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 1 /* dedicated */);
int CCEIndex = allocate_nr_CCEs(
nr_mac,
bwp,
coreset,
aggregation_level,
UE_info->rnti[UE_id],
0); // m
const int cid = coreset->controlResourceSetId;
const uint16_t Y = UE_info->Y[UE_id][cid][nr_mac->current_slot];
const int m = UE_info->num_pdcch_cand[UE_id][cid];
int CCEIndex = allocate_nr_CCEs(nr_mac,
bwp,
coreset,
aggregation_level,
Y,
m,
nr_of_candidates);
if (CCEIndex < 0) {
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
pusch_sched->active = false;
return;
}
else {
UE_info->num_pdcch_cand[UE_id][cid]++;
nr_configure_pdcch(nr_mac,
pdcch_pdu_rel15,
UE_info->rnti[UE_id],
@@ -172,8 +172,9 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
NR_BWP_Downlink_t *bwp,
NR_ControlResourceSet_t *coreset,
int aggregation,
uint16_t n_RNTI,
int m) {
uint16_t Y,
int m,
int nr_of_candidates) {
// uncomment these when we allocate for common search space
// NR_COMMON_channels_t *cc = nr_mac->common_channels;
// NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
@@ -189,15 +190,19 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
n_rb*=6;
uint16_t N_reg = n_rb * coreset->duration;
uint16_t n_CI=0;
const uint32_t A[3]={39827,39829,39839};
/* if n_RNTI is zero, this results in zero, too! */
uint16_t Y = (A[0]*n_RNTI)%65537; // Candidate 0, antenna port 0
uint16_t n_CI = 0;
uint16_t N_cce = N_reg / NR_NB_REG_PER_CCE;
const uint16_t N_cce = N_reg / NR_NB_REG_PER_CCE;
const uint16_t M_s_max = nr_of_candidates;
uint16_t M_s_max = (aggregation==4)?4:(aggregation==8)?2:1;
int first_cce = aggregation * (( Y + (m*N_cce)/(aggregation*M_s_max) + n_CI ) % CEILIDIV(N_cce,aggregation));
AssertFatal(m < nr_of_candidates,
"PDCCH candidate index %d in CORESET %d exceeds the maximum "
"number of PDCCH candidates (%d)\n",
m,
coreset_id,
nr_of_candidates);
int first_cce = aggregation * (( Y + CEILIDIV((m*N_cce),(aggregation*M_s_max)) + n_CI ) % CEILIDIV(N_cce,aggregation));
for (int i=0;i<aggregation;i++)
if (cce_list[first_cce+i] != 0) return(-1);
@@ -427,27 +432,17 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
}
void nr_fill_nfapi_dl_pdu(int Mod_idP,
int UE_id,
int bwp_id,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
nfapi_nr_dl_tti_request_body_t *dl_req,
rnti_t rnti,
NR_CellGroupConfig_t *secondaryCellGroup,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_sched_pucch *pucch_sched,
int nrOfLayers,
uint8_t mcs,
uint16_t rbSize,
uint16_t rbStart,
uint8_t numDmrsCdmGrpsNoData,
nfapi_nr_dmrs_type_e dmrsConfigType,
uint8_t table_idx,
uint16_t R,
uint8_t Qm,
uint32_t TBS,
int time_domain_assignment,
int StartSymbolIndex,
int NrOfSymbols,
uint8_t aggregation_level,
int CCEIndex,
int harq_pid,
int ndi,
int round) {
@@ -455,9 +450,10 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
const int bwp_id = sched_ctrl->active_bwp->bwp_Id;
const int nrOfLayers = 1;
const int mcs = sched_ctrl->mcs;
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
@@ -482,7 +478,7 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
pdsch_pdu_rel15->pduBitmap = 0;
pdsch_pdu_rel15->rnti = UE_info->rnti[UE_id];
pdsch_pdu_rel15->rnti = rnti;
pdsch_pdu_rel15->pduIndex = nr_mac->pdu_index[0]++;
// BWP
@@ -507,20 +503,19 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
pdsch_pdu_rel15->dmrsConfigType = dmrsConfigType;
pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
pdsch_pdu_rel15->SCID = 0;
pdsch_pdu_rel15->numDmrsCdmGrpsNoData = numDmrsCdmGrpsNoData;
pdsch_pdu_rel15->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
pdsch_pdu_rel15->dmrsPorts = 1;
pdsch_pdu_rel15->resourceAlloc = 1;
pdsch_pdu_rel15->rbStart = rbStart;
pdsch_pdu_rel15->rbSize = rbSize;
pdsch_pdu_rel15->rbStart = sched_ctrl->rbStart;
pdsch_pdu_rel15->rbSize = sched_ctrl->rbSize;
pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
pdsch_pdu_rel15->targetCodeRate[0] = R;
pdsch_pdu_rel15->qamModOrder[0] = Qm;
pdsch_pdu_rel15->TBSize[0] = TBS;
pdsch_pdu_rel15->mcsTable[0] = table_idx;
pdsch_pdu_rel15->mcsTable[0] = sched_ctrl->mcsTableIdx;
pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
// k0 = *bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0;
pdsch_pdu_rel15->dlDmrsSymbPos =
fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
scc->dmrs_TypeA_Position,
@@ -545,8 +540,8 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
275));
else
AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n");
// time domain assignment
dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV;
// time domain assignment: row index used instead of SLIV
dci_pdu_rel15[0].time_domain_assignment.val = sched_ctrl->time_domain_allocation;
// mcs and rv
dci_pdu_rel15[0].mcs = mcs;
dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
@@ -557,7 +552,7 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3;
// TPC for PUCCH
dci_pdu_rel15[0].tpc = UE_info->UE_sched_ctrl[UE_id].tpc1; // table 7.2.1-1 in 38.213
dci_pdu_rel15[0].tpc = sched_ctrl->tpc1; // table 7.2.1-1 in 38.213
// PUCCH resource indicator
dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator;
// PDSCH to HARQ TI
@@ -582,18 +577,18 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
nr_configure_pdcch(nr_mac,
pdcch_pdu_rel15,
UE_info->rnti[UE_id],
ss,
coreset,
rnti,
sched_ctrl->search_space,
sched_ctrl->coreset,
scc,
bwp,
aggregation_level,
CCEIndex);
sched_ctrl->aggregation_level,
sched_ctrl->cce_index);
int dci_formats[2];
int rnti_types[2];
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats)
if (sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats)
dci_formats[0] = NR_DL_DCI_FORMAT_1_1;
else
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
@@ -613,17 +608,6 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
pdcch_pdu_rel15->StartSymbolIndex,
pdcch_pdu_rel15->DurationSymbols);
// I don't know why the following is not needed, but in this case we don't
// need additional calculations:
//const uint16_t N_RE_prime = NR_NB_SC_PER_RB * N_sh_symb - N_PRB_DMRS - N_PRB_oh;
//LOG_D(MAC,
// "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n",
// N_RE_prime,
// N_sh_symb,
// N_PRB_DMRS,
// N_PRB_oh);
//pdsch_pdu_rel15->nb_mod_symbols = N_RE_prime*pdsch_pdu_rel15->n_prb*pdsch_pdu_rel15->nb_codewords;
LOG_D(MAC,
"DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d "
"nb_layers %d nb_codewords %d mcs %d TBS: %d\n",
@@ -730,10 +714,11 @@ void nr_configure_pdcch(gNB_MAC_INST *nr_mac,
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
NR_ServingCellConfigCommon_t *scc,
NR_BWP_Uplink_t *bwp,
uint16_t rnti,
uint8_t pucch_resource,
uint16_t O_uci,
uint16_t O_csi,
uint16_t O_ack,
uint8_t SR_flag) {
uint8_t O_sr) {
NR_PUCCH_Config_t *pucch_Config;
NR_PUCCH_Resource_t *pucchres;
@@ -748,6 +733,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->bit_len_harq = O_ack;
uint16_t O_uci = O_csi + O_ack;
if (bwp) { // This is not the InitialBWP
NR_PUSCH_Config_t *pusch_Config = bwp->bwp_Dedicated->pusch_Config->choice.setup;
@@ -810,7 +797,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
else
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
}
else {
if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) {
N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706;
if (N2<O_uci && N3>O_uci) {
if (pucch_resource < n_list)
@@ -836,6 +823,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
if (pucchres->pucch_ResourceId == *resource_id) {
res_found = 1;
pucch_pdu->prb_start = pucchres->startingPRB;
pucch_pdu->rnti = rnti;
// FIXME why there is only one frequency hopping flag
// what about inter slot frequency hopping?
pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0;
@@ -846,7 +834,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
pucch_pdu->sr_flag = SR_flag;
pucch_pdu->sr_flag = O_sr;
break;
case NR_PUCCH_Resource__format_PR_format1 :
pucch_pdu->format_type = 1;
@@ -854,21 +842,23 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC;
pucch_pdu->sr_flag = SR_flag;
pucch_pdu->sr_flag = O_sr;
break;
case NR_PUCCH_Resource__format_PR_format2 :
pucch_pdu->format_type = 2;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
pucch_pdu->prb_size = pucchres->format.choice.format2->nrofPRBs;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId;
pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs,
O_uci+O_sr,O_csi,pucch_Config->format2->choice.setup->maxCodeRate,
2,pucchres->format.choice.format2->nrofSymbols,8);
pucch_pdu->bit_len_csi_part1 = O_csi;
break;
case NR_PUCCH_Resource__format_PR_format3 :
pucch_pdu->format_type = 3;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
pucch_pdu->prb_size = pucchres->format.choice.format3->nrofPRBs;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
if (pucch_Config->format3 == NULL) {
pucch_pdu->pi_2bpsk = 0;
@@ -879,6 +869,19 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
}
int f3_dmrs_symbols;
if (pucchres->format.choice.format3->nrofSymbols==4)
f3_dmrs_symbols = 1<<pucch_pdu->freq_hop_flag;
else {
if(pucchres->format.choice.format3->nrofSymbols<10)
f3_dmrs_symbols = 2;
else
f3_dmrs_symbols = 2<<pucch_pdu->add_dmrs_flag;
}
pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs,
O_uci+O_sr,O_csi,pucch_Config->format3->choice.setup->maxCodeRate,
2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12);
pucch_pdu->bit_len_csi_part1 = O_csi;
break;
case NR_PUCCH_Resource__format_PR_format4 :
pucch_pdu->format_type = 4;
@@ -896,6 +899,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
}
pucch_pdu->bit_len_csi_part1 = O_csi;
break;
default :
AssertFatal(1==0,"Undefined PUCCH format \n");
@@ -911,6 +915,84 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
}
uint16_t compute_pucch_prb_size(uint8_t format,
uint8_t nr_prbs,
uint16_t O_tot,
uint16_t O_csi,
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
uint8_t Qm,
uint8_t n_symb,
uint8_t n_re_ctrl) {
uint16_t O_crc;
if (O_tot<12)
O_crc = 0;
else{
if (O_tot<20)
O_crc = 6;
else {
if (O_tot<360)
O_crc = 11;
else
AssertFatal(1==0,"Case for segmented PUCCH not yet implemented");
}
}
int rtimes100;
switch(*maxCodeRate){
case NR_PUCCH_MaxCodeRate_zeroDot08 :
rtimes100 = 8;
break;
case NR_PUCCH_MaxCodeRate_zeroDot15 :
rtimes100 = 15;
break;
case NR_PUCCH_MaxCodeRate_zeroDot25 :
rtimes100 = 25;
break;
case NR_PUCCH_MaxCodeRate_zeroDot35 :
rtimes100 = 35;
break;
case NR_PUCCH_MaxCodeRate_zeroDot45 :
rtimes100 = 45;
break;
case NR_PUCCH_MaxCodeRate_zeroDot60 :
rtimes100 = 60;
break;
case NR_PUCCH_MaxCodeRate_zeroDot80 :
rtimes100 = 80;
break;
default :
AssertFatal(1==0,"Invalid MaxCodeRate");
}
float r = (float)rtimes100/100;
if (O_csi == O_tot) {
if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r))
AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs",
r,O_tot,O_crc,nr_prbs);
else
return nr_prbs;
}
if (format==2){
// TODO fix this for multiple CSI reports
for (int i=1; i<=nr_prbs; i++){
if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) &&
(O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r))
return i;
}
AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs",
r,O_tot,O_crc,nr_prbs);
}
else{
AssertFatal(1==0,"Not yet implemented");
}
}
void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
dci_pdu_rel15_t *dci_pdu_rel15,
nr_dci_format_t format,
@@ -1526,6 +1608,7 @@ void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc,
pos+=1;
*dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos);
}
LOG_D(MAC, "DCI index %d has %d bits and the payload is %lx\n", d, dci_size, *dci_pdu);
}
}
@@ -1602,6 +1685,20 @@ inline void add_nr_ue_list(NR_UE_list_t *listP, int UE_id) {
*cur = UE_id;
}
/*
* Remove a UE from NR_UE_list listP
*/
inline int remove_nr_ue_list(NR_UE_list_t *listP, int UE_id) {
int *cur = &listP->head;
while (*cur != -1 && *cur != UE_id)
cur = &listP->next[*cur];
AssertFatal(*cur != -1, "UE %d not found in UE_list\n", UE_id);
int *next = &listP->next[*cur];
*cur = listP->next[*cur];
*next = -1;
return 1;
}
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP)
//------------------------------------------------------------------------------
{
@@ -1619,9 +1716,23 @@ int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP)
return -1;
}
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP)
void set_Y(int Y[3][160], rnti_t rnti) {
const int A[3] = {39827, 39829, 39839};
const int D = 65537;
Y[0][0] = (A[0] * rnti) % D;
Y[1][0] = (A[1] * rnti) % D;
Y[2][0] = (A[2] * rnti) % D;
for (int s = 1; s < 160; s++) {
Y[0][s] = (A[0] * Y[0][s - 1]) % D;
Y[1][s] = (A[1] * Y[1][s - 1]) % D;
Y[2][s] = (A[2] * Y[2][s - 1]) % D;
}
}
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) {
//------------------------------------------------------------------------------
{
int RA_id;
RA_t *ra = (RA_t *) &RC.nrmac[mod_idP]->common_channels[CC_idP].ra[0];
@@ -1637,6 +1748,7 @@ int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP)
return -1;
}
//------------------------------------------------------------------------------
int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
@@ -1661,18 +1773,25 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
UE_info->active[UE_id] = true;
UE_info->rnti[UE_id] = rntiP;
add_nr_ue_list(&UE_info->list, UE_id);
set_Y(UE_info->Y[UE_id], rntiP);
memset((void *) &UE_info->UE_sched_ctrl[UE_id],
0,
sizeof(NR_UE_sched_ctrl_t));
UE_info->UE_sched_ctrl[UE_id].ta_timer = 100;
UE_info->UE_sched_ctrl[UE_id].ta_frame = 0;
UE_info->UE_sched_ctrl[UE_id].ta_update = 31;
UE_info->UE_sched_ctrl[UE_id].ta_apply = false;
UE_info->UE_sched_ctrl[UE_id].ul_rssi = 0;
UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch *)malloc(num_slots_ul*sizeof(NR_sched_pucch));
UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch **)malloc(num_slots_ul*sizeof(NR_sched_pucch *));
for (int s=0; s<num_slots_ul;s++)
UE_info->UE_sched_ctrl[UE_id].sched_pucch[s] = (NR_sched_pucch *)malloc(2*sizeof(NR_sched_pucch));
UE_info->UE_sched_ctrl[UE_id].sched_pusch = (NR_sched_pusch *)malloc(num_slots_ul*sizeof(NR_sched_pusch));
for (int k=0; k<num_slots_ul; k++) {
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k],
0,
sizeof(NR_sched_pucch));
for (int l=0; l<2; l++)
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
0,
sizeof(NR_sched_pucch));
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k],
0,
sizeof(NR_sched_pusch));
@@ -1703,6 +1822,7 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
for (i = 0; i < MAX_MOBILES_PER_GNB; i++) {
if (UE_info->active[i] != TRUE)
continue;
if (UE_info->rnti[i] != rnti)
@@ -1710,9 +1830,11 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
/* UE found, remove it */
UE_id = i;
UE_info->num_UEs--;
UE_info->active[UE_id] = FALSE;
UE_info->rnti[UE_id] = 0;
remove_nr_ue_list(&UE_info->list, UE_id);
free(UE_info->UE_sched_ctrl[UE_id].sched_pucch);
free(UE_info->UE_sched_ctrl[UE_id].sched_pusch);
memset((void *) &UE_info->UE_sched_ctrl[UE_id],
@@ -1794,50 +1916,302 @@ void get_pdsch_to_harq_feedback(int Mod_idP,
}
}
uint16_t nr_get_csi_bitlen(int Mod_idP,
int UE_id,
uint8_t csi_report_id) {
uint16_t csi_bitlen =0;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL;
CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]);
csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
(CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report);
return csi_bitlen;
}
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
int *period, int *offset) {
NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
switch(p_and_o){
case NR_CSI_ReportPeriodicityAndOffset_PR_slots4:
*period = 4;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots5:
*period = 5;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots8:
*period = 8;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots10:
*period = 10;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots16:
*period = 16;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots20:
*period = 20;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots40:
*period = 40;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots80:
*period = 80;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots160:
*period = 160;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots320:
*period = 320;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320;
break;
default:
AssertFatal(1==0,"No periodicity and offset resource found in CSI report");
}
}
//!TODO : same function can be written to handle csi_resources
void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) {
uint8_t csi_report_id = 0;
uint8_t csi_resourceidx =0;
uint8_t csi_ssb_idx =0;
NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement;
UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present;
for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId)
continue;
else {
//Finding the CSI_RS or SSB Resources
UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present;
if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){
struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB;
UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0;
UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0;
}
if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){
uint8_t nb_ssb_resources =0;
for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
*(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled ==
csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) {
if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
else
/*! From Spec 38.331
* nrofReportedRS
* The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
* capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
* When the field is absent the UE applies the value 1
*/
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1;
}else
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2;
nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
if (nb_ssb_resources){
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources));
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
}
else{
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0;
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0;
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0;
}
LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d",
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen,
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen,
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen);
break ;
}
}
}
if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report){
AssertFatal(1==0,"Currently configuring only SSB beamreporting.");
}
break;
}
}
}
}
void nr_csi_meas_reporting(int Mod_idP,
int UE_id,
frame_t frame,
sub_frame_t slot,
int slots_per_tdd,
int ul_slots,
int n_slots_frame) {
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
NR_sched_pucch *curr_pucch;
NR_PUCCH_ResourceSet_t *pucchresset;
NR_CSI_ReportConfig_t *csirep;
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available");
for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently");
int period, offset, sched_slot;
csi_period_offset(csirep,&period,&offset);
sched_slot = (period+offset)%n_slots_frame;
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
// preparation is done in first slot of tdd period
if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) {
// we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack)
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[sched_slot-slots_per_tdd+ul_slots][0];
NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
int found = -1;
pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
int n_list = pucchresset->resourceList.list.count;
for (int i=0; i<n_list; i++) {
if (*pucchresset->resourceList.list.array[i] == pucchcsires->pucch_Resource)
found = i;
}
AssertFatal(found>-1,"CSI resource not found among PUCCH resources");
curr_pucch->resource_indicator = found;
n_list = pucch_Config->resourceToAddModList->list.count;
// going through the list of PUCCH resources to find the one indexed by resource_id
for (int i=0; i<n_list; i++) {
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i];
if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) {
switch(pucchres->format.present){
case NR_PUCCH_Resource__format_PR_format2:
if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
curr_pucch->simultaneous_harqcsi = false;
else
curr_pucch->simultaneous_harqcsi = true;
break;
case NR_PUCCH_Resource__format_PR_format3:
if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
curr_pucch->simultaneous_harqcsi = false;
else
curr_pucch->simultaneous_harqcsi = true;
break;
case NR_PUCCH_Resource__format_PR_format4:
if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
curr_pucch->simultaneous_harqcsi = false;
else
curr_pucch->simultaneous_harqcsi = true;
break;
default:
AssertFatal(1==0,"Invalid PUCCH format type");
}
}
}
curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size
curr_pucch->frame = frame;
curr_pucch->ul_slot = sched_slot;
}
}
}
// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
void nr_update_pucch_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id) {
void nr_acknack_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id,
int *pucch_occ) {
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
NR_sched_pucch *curr_pucch;
int first_ul_slot_tdd,k,i;
int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l;
uint8_t pdsch_to_harq_feedback[8];
int found = 0;
int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
nr_ulmix_slots++;
bool csi_pres=false;
for (k=0; k<nr_ulmix_slots; k++) {
if(UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0)
csi_pres=true;
}
// As a preference always schedule ack nacks in PUCCH0 (max 2 per slots)
// Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot
if (csi_pres)
max_acknacks=10;
else
max_acknacks=2;
// this is hardcoded for now as ue specific
NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
// for each possible ul or mixed slot
for (k=0; k<nr_ulmix_slots; k++) {
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k];
// if there is free room in current pucch structure
if (curr_pucch->dai_c<MAX_ACK_BITS) {
curr_pucch->frame = frameP;
curr_pucch->dai_c++;
curr_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource
// first pucch occasion in first UL or MIXED slot
first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
i = 0;
while (i<8 && found == 0) { // look if timing indicator is among allowed values
if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) {
// computing slot in which pucch is scheduled
curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
curr_pucch->timing_indicator = i; // index in the list of timing indicators
*pucch_id = k;
return;
for (l=0; l<1; l++) { // scheduling 2 PUCCH in a single slot does not work with the phone, currently
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
//if it is possible to schedule acknack in current pucch (no exclusive csi pucch)
if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) {
// if there is free room in current pucch structure
if (curr_pucch->dai_c<max_acknacks) {
pucch_res = get_pucch_resource(UE_info,UE_id,k,l);
if (pucch_res>-1){
curr_pucch->resource_indicator = pucch_res;
curr_pucch->frame = frameP;
// first pucch occasion in first UL or MIXED slot
first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
i = 0;
while (i<8 && found == 0) { // look if timing indicator is among allowed values
if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) {
// computing slot in which pucch is scheduled
curr_pucch->dai_c++;
curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
curr_pucch->timing_indicator = i; // index in the list of timing indicators
*pucch_id = k;
*pucch_occ = l;
return;
}
}
}
}
}
}
@@ -1845,6 +2219,22 @@ void nr_update_pucch_scheduling(int Mod_idP,
}
int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) {
// to be updated later, for now simple implementation
// use the second allocation just in case there is csi in the first
// in that case use second resource (for a different symbol) see 9.2 in 38.213
if (l==1) {
if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0)
return -1;
else
return 1;
}
else
return 0;
}
void find_aggregation_candidates(uint8_t *aggregation_level,
uint8_t *nr_of_candidates,
NR_SearchSpace_t *ss) {
@@ -214,12 +214,8 @@ void nr_process_mac_pdu(
int UE_id = find_nr_UE_id(module_idP, rnti);
RC.nrmac[module_idP]->UE_info.mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP);
log_dump(MAC, pdu_ptr + mac_subheader_len, 32, LOG_DUMP_CHAR, "\n");
for (i = 0; i < 32; i++)
LOG_T(MAC, "%x.", (pdu_ptr + mac_subheader_len)[i]);
LOG_T(MAC, "\n");
#endif
if(IS_SOFTMODEM_NOS1){
mac_rlc_data_ind(module_idP,
@@ -322,6 +318,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
UE_info = &gNB_mac->UE_info;
int target_snrx10 = gNB_mac->pusch_target_snrx10;
if (sduP != NULL) {
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
T_BUFFER(sduP, sdu_lenP));
}
if (UE_id != -1) {
UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
@@ -349,6 +351,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
}
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_I(MAC, "Printing received UL MAC payload at gNB side: %d \n");
for (int i = 0; i < sdu_lenP ; i++) {
//harq_process_ul_ue->a[i] = (unsigned char) rand();
@@ -356,6 +359,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
printf("%02x ",(unsigned char)sduP[i]);
}
printf("\n");
#endif
if (sduP != NULL){
@@ -365,46 +369,54 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
else {
}
}
else if (sduP != NULL) { // if the CRC passed
// random access pusch with TC-RNTI
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0];
if (ra->state != WAIT_Msg3) {
LOG_E(MAC,
"expected RA state WAIT_Msg3/%d (but is %d) for RA-RNTI %04x\n",
WAIT_Msg3,
ra->state,
ra->rnti);
} else {
if (!sduP) // check that CRC passed
return;
}
if (ra->rnti != current_rnti) {
LOG_E(MAC,
"expected RA-RNTI %04x (C-RNTI %04x) to match current RNTI %04x\n",
ra->rnti,
ra->crnti,
current_rnti);
return;
}
free(ra->preambles.preamble_list);
ra->state = RA_IDLE;
LOG_I(MAC, "reset RA state information for RA-RNTI %04x\n", ra->rnti);
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->crnti);
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
UE_info->UE_beam_index[UE_id] = ra->beam_id;
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList =
ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
AssertFatal(bwpList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
bwpList->list.count);
const int bwp_id = 1;
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
LOG_W(MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
"adding UE MAC Context UE_id %d/RNTI %04x\n",
gnb_mod_idP,
current_rnti,
UE_id,
ra->crnti);
}
}
/* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
* and check the corresponding UE's RNTI match, in which case we activate
* it. */
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->state != WAIT_Msg3)
continue;
// random access pusch with TC-RNTI
if (ra->rnti != current_rnti) {
LOG_W(MAC,
"expected TC-RNTI %04x to match current RNTI %04x\n",
ra->rnti,
current_rnti);
continue;
}
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti);
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
compute_csi_bitlen(ra->secondaryCellGroup, UE_info, UE_id);
UE_info->UE_beam_index[UE_id] = ra->beam_id;
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
AssertFatal(bwpList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
bwpList->list.count);
const int bwp_id = 1;
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
LOG_I(MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
"adding UE MAC Context UE_id %d/RNTI %04x\n",
gnb_mod_idP,
current_rnti,
UE_id,
ra->rnti);
// re-initialize ta update variables afrer RA procedure completion
UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP;
free(ra->preambles.preamble_list);
ra->state = RA_IDLE;
LOG_I(MAC,
"reset RA state information for RA-RNTI %04x/index %d\n",
ra->rnti,
i);
return;
}
}
}
+57 -46
View File
@@ -36,8 +36,6 @@
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_TAG-Id.h"
#define MAX_ACK_BITS 2 //only format 0 is available for now
void set_cset_offset(uint16_t);
void mac_top_init_gNB(void);
@@ -82,7 +80,13 @@ void nr_schedule_ue_spec(module_id_t module_id,
sub_frame_t slot,
int num_slots_per_tdd);
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);
/* \brief default preprocessor */
void nr_simple_dlsch_preprocessor(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd);
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, uint8_t slots_per_frame);
/////// Random Access MAC-PHY interface functions and primitives ///////
@@ -126,42 +130,37 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs);
/////// Phy test scheduler ///////
/* \brief preprocessor for phytest: schedules UE_id 0 with fixed MCS on all
* freq resources */
void nr_preprocessor_phytest(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd);
void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP);
void nr_fill_nfapi_dl_pdu(int Mod_id,
int UE_id,
int bwp_id,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
nfapi_nr_dl_tti_request_body_t *dl_req,
rnti_t rnti,
NR_CellGroupConfig_t *secondaryCellGroup,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_sched_pucch *pucch_sched,
int nrOfLayers,
uint8_t mcs,
uint16_t rbSize,
uint16_t rbStart,
uint8_t numDmrsCdmGrpsNoData,
nfapi_nr_dmrs_type_e dmrsConfigType,
uint8_t table_idx,
uint16_t R,
uint8_t Qm,
uint32_t tbs,
int time_domain_assignment,
int StartSymbolIndex,
int NrOfSymbols,
uint8_t aggregation_level,
int CCEIndex,
int harq_pid,
int ndi,
int round);
int configure_fapi_dl_pdu_phytest(int Mod_id,
nfapi_nr_dl_tti_request_body_t *dl_req,
NR_sched_pucch *pucch_sched,
uint8_t *mcsIndex,
uint16_t *rbSize,
uint16_t *rbStart);
void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch,
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234,
NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats);
void config_uldci(NR_BWP_Uplink_t *ubwp,
nfapi_nr_pusch_pdu_t *pusch_pdu,
@@ -171,20 +170,6 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,
int time_domain_assignment, uint8_t tpc,
int n_ubwp, int bwp_id);
void configure_fapi_dl_Tx(module_id_t Mod_idP,
frame_t frameP,
sub_frame_t slotP,
nfapi_nr_dl_tti_request_body_t *dl_req,
nfapi_nr_pdu_t *tx_req,
int tbs_bytes,
int16_t pdu_index);
void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t slotP,
NR_sched_pucch *pucch_sched,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_config);
void nr_schedule_pusch(int Mod_idP,
int UE_id,
int num_slots_per_tdd,
@@ -198,12 +183,23 @@ void nr_schedule_pucch(int Mod_idP,
frame_t frameP,
sub_frame_t slotP);
void nr_update_pucch_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id);
void nr_csi_meas_reporting(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int ul_slots,
int n_slots_frame);
void nr_acknack_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id,
int *pucch_occ);
int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l);
void get_pdsch_to_harq_feedback(int Mod_idP,
int UE_id,
@@ -232,10 +228,11 @@ int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space,
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
NR_ServingCellConfigCommon_t *scc,
NR_BWP_Uplink_t *bwp,
uint16_t rnti,
uint8_t pucch_resource,
uint16_t O_uci,
uint16_t O_csi,
uint16_t O_ack,
uint8_t SR_flag);
uint8_t O_sr);
void find_search_space(int ss_type,
NR_BWP_Downlink_t *bwp,
@@ -316,8 +313,20 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
NR_BWP_Downlink_t *bwp,
NR_ControlResourceSet_t *coreset,
int aggregation,
uint16_t n_RNTI,
int m);
uint16_t Y,
int m,
int nr_of_candidates);
uint16_t compute_pucch_prb_size(uint8_t format,
uint8_t nr_prbs,
uint16_t O_tot,
uint16_t O_csi,
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
uint8_t Qm,
uint8_t n_symb,
uint8_t n_re_ctrl);
void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id);
int get_dlscs(nfapi_nr_config_request_t *cfg);
@@ -365,6 +374,8 @@ int binomial(int n, int k);
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot);
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int CC_id);
/* \brief Function to indicate a received SDU on ULSCH.
@param Mod_id Instance ID of gNB
+5
View File
@@ -82,6 +82,11 @@ void mac_top_init_gNB(void)
RC.nrmac[i]->ul_handle = 0;
if (get_softmodem_params()->phy_test)
RC.nrmac[i]->pre_processor_dl = nr_preprocessor_phytest;
else
RC.nrmac[i]->pre_processor_dl = nr_simple_dlsch_preprocessor;
}//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n");
+55 -5
View File
@@ -68,6 +68,9 @@
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "NR_TAG.h"
#include <openair3/UICC/usim_interface.h>
/* Defs */
#define MAX_NUM_BWP 2
#define MAX_NUM_CORESET 2
@@ -155,6 +158,8 @@ typedef struct {
NR_preamble_ue_t preambles;
/// NSA: the UEs C-RNTI to use
rnti_t crnti;
/// CFRA flag
bool cfra;
} NR_RA_t;
/*! \brief gNB common channels */
@@ -186,9 +191,9 @@ typedef struct {
/// Template for RA computations
NR_RA_t ra[NR_NB_RA_PROC_MAX];
/// VRB map for common channels
uint8_t vrb_map[275];
uint16_t vrb_map[275];
/// VRB map for common channels and retransmissions by PHICH
uint8_t vrb_map_UL[275];
uint16_t vrb_map_UL[275];
/// number of subframe allocation pattern available for MBSFN sync area
uint8_t num_sf_allocation_pattern;
///Number of active SSBs
@@ -272,10 +277,12 @@ typedef struct UE_info {
typedef struct NR_sched_pucch {
int frame;
int ul_slot;
bool sr_flag;
int csi_bits;
bool simultaneous_harqcsi;
uint8_t dai_c;
uint8_t timing_indicator;
uint8_t resource_indicator;
bool active;
} NR_sched_pucch;
typedef struct NR_sched_pusch {
@@ -313,6 +320,25 @@ typedef struct NR_UE_ul_harq {
NR_UL_harq_states_t state;
} NR_UE_ul_harq_t;
typedef struct {
uint8_t nb_ssbri_cri;
uint8_t cri_ssbri_bitlen;
uint8_t rsrp_bitlen;
uint8_t diff_rsrp_bitlen;
}CRI_SSBRI_RSRP_bitlen_t;
#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16
typedef struct nr_csi_report {
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR CSI_Resource_type;
uint8_t nb_of_nzp_csi_report;
uint8_t nb_of_csi_ssb_report;
CRI_SSBRI_RSRP_bitlen_t CSI_report_bitlen[MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG];
} nr_csi_report_t;
/*! \brief scheduling control information set through an API */
typedef struct {
/// total amount of data awaiting for this UE
@@ -322,9 +348,10 @@ typedef struct {
/// the currently active BWP in DL
NR_BWP_Downlink_t *active_bwp;
NR_sched_pucch *sched_pucch;
NR_sched_pucch **sched_pucch;
/// selected PUCCH index, if scheduled
int pucch_sched_idx;
int pucch_occ_idx;
NR_sched_pusch *sched_pusch;
/// CCE index and aggregation, should be coherent with cce_list
@@ -348,7 +375,7 @@ typedef struct {
/// Retransmission-related information
NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES];
uint16_t ta_timer;
uint16_t ta_frame;
int16_t ta_update;
bool ta_apply;
uint8_t tpc0;
@@ -362,7 +389,11 @@ typedef struct {
} NR_UE_sched_ctrl_t;
typedef struct {
boolean_t fiveG_connected;
uicc_t *uicc;
} NRUEcontext_t;
typedef struct {
int lc_bytes_tx[64];
int lc_bytes_rx[64];
int dlsch_rounds[8];
@@ -375,6 +406,7 @@ typedef struct {
} NR_mac_stats_t;
/*! \brief UNR_E_list_t is a "list" of users within UE_info_t. Especial useful in
* the scheduler and to keep "classes" of users. */
typedef struct {
@@ -382,21 +414,34 @@ typedef struct {
int next[MAX_MOBILES_PER_GNB];
} NR_UE_list_t;
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
#define MAX_CSI_REPORTCONFIG 48
typedef struct {
DLSCH_PDU DLSCH_pdu[4][MAX_MOBILES_PER_GNB];
/// scheduling control info
nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG];
NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB];
NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB];
NR_UE_list_t list;
int num_UEs;
bool active[MAX_MOBILES_PER_GNB];
rnti_t rnti[MAX_MOBILES_PER_GNB];
NR_CellGroupConfig_t *secondaryCellGroup[MAX_MOBILES_PER_GNB];
/// CCE indexing
int Y[MAX_MOBILES_PER_GNB][3][160];
int m[MAX_MOBILES_PER_GNB];
int num_pdcch_cand[MAX_MOBILES_PER_GNB][MAX_NUM_CORESET];
// UE selected beam index
uint8_t UE_beam_index[MAX_MOBILES_PER_GNB];
} NR_UE_info_t;
typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd);
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -457,6 +502,11 @@ typedef struct gNB_MAC_INST_s {
time_stats_t schedule_pch;
/// CCE lists
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
/// current slot
int current_slot;
/// DL preprocessor for differentiated scheduling
nr_pp_impl_dl pre_processor_dl;
} gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */
+2 -12
View File
@@ -996,17 +996,7 @@ pdcp_data_ind(
* TODO: be sure of this
*/
if (NFAPI_MODE == NFAPI_UE_STUB_PNF ) {
#ifdef UESIM_EXPANSION
if (UE_NAS_USE_TUN) {
pdcpHead->inst = ctxt_pP->module_id;
} else {
pdcpHead->inst = 0;
}
#else
pdcpHead->inst = ctxt_pP->module_id;
#endif
} else { // nfapi_mode
if (UE_NAS_USE_TUN) {
pdcpHead->inst = ctxt_pP->module_id;
@@ -1035,7 +1025,7 @@ pdcp_data_ind(
pushNotifiedFIFO(&pdcp_sdu_list, new_sdu_p);
/* Print octets of incoming data in hexadecimal form */
LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
sdu_buffer_sizeP - payload_offset + (int)sizeof(pdcp_data_ind_header_t),
sdu_buffer_sizeP - payload_offset);
//util_print_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset);
@@ -2287,7 +2277,7 @@ uint64_t pdcp_module_init( uint64_t pdcp_optmask ) {
nas_getparams();
if(UE_NAS_USE_TUN) {
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1;
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1;
netlink_init_tun("ue",num_if);
if (IS_SOFTMODEM_NOS1)
nas_config(1, 1, 2, "ue");
-3
View File
@@ -53,9 +53,6 @@ typedef rlc_op_status_t (*send_rlc_data_req_func_t)(const protocol_ctxt_t *cons
typedef boolean_t (*pdcp_data_ind_func_t)( const protocol_ctxt_t *, const srb_flag_t,
const MBMS_flag_t, const rb_id_t, const sdu_size_t,
mem_block_t *,const uint32_t *const, const uint32_t *const);
/* maximum number of tun interfaces that will be created to emulates UEs */
/* UEs beyond that will be multiplexed on the same tun */
#define MAX_NUMBER_NETIF 16
#define ENB_NAS_USE_TUN_W_MBMS_BIT (1<< 10)
#define PDCP_USE_NETLINK_BIT (1<< 11)
+3 -12
View File
@@ -86,12 +86,6 @@ extern struct msghdr nas_msg_rx;
#ifdef UESIM_EXPANSION
extern uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX];
#endif
# include "gtpv1u_eNB_task.h"
# include "gtpv1u_eNB_defs.h"
@@ -156,9 +150,9 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) {
nas_nlh_tx->nlmsg_len = sizeToWrite;
ret = sendmsg(nas_sock_fd[0],&nas_msg_tx,0);
} // PDCP_USE_NETLINK
AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s), nas_sock_fd[0]: %d\n", errno, strerror(errno), nas_sock_fd[0]);
AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s), nas_sock_fd[0]: %d\n", errno, strerror(errno), nas_sock_fd[0]);
if( LOG_DEBUGFLAG(DEBUG_PDCP) )
log_dump(PDCP, pdcpData, min(sizeToWrite,30) , LOG_DUMP_CHAR,
"Printing first bytes of PDCP SDU before removing it from the list: \n");
@@ -202,6 +196,7 @@ int pdcp_fifo_flush_mbms_sdus(const protocol_ctxt_t *const ctxt_pP) {
//} // PDCP_USE_NETLINK
//AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno));
//AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno));
delNotifiedFIFO_elt (sdu_p);
pdcp_nb_sdu_sent ++;
@@ -503,11 +498,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const ctx
}
} else { // ctxt.enb_flag => UE
if (NFAPI_MODE == NFAPI_UE_STUB_PNF) {
#ifdef UESIM_EXPANSION
ctxt.module_id = inst_pdcp_list[pdcp_read_header_g.inst];
#else
ctxt.module_id = pdcp_read_header_g.inst;
#endif
} else {
ctxt.module_id = 0;
}
+1 -1
View File
@@ -143,7 +143,7 @@ void (*rlc_rrc_data_conf)(
const protocol_ctxt_t *const ctxtP,
const rb_id_t rb_idP,
const mui_t muiP,
const rlc_tx_status_t statusP);
const rlc_tx_status_t statusP) __attribute__ ((aligned(32)));
typedef void (rrc_data_ind_cb_t)(
const protocol_ctxt_t *const ctxtP,
+8 -2
View File
@@ -19,6 +19,9 @@
* contact@openairinterface.org
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "nr_pdcp_ue_manager.h"
#include "NR_RadioBearerConfig.h"
#include "NR_RLC-BearerConfig.h"
@@ -43,6 +46,7 @@ static uint64_t pdcp_optmask;
/* rlc_data_req queue - begin */
/****************************************************************************/
#include <pthread.h>
/* NR PDCP and RLC both use "big locks". In some cases a thread may do
@@ -92,6 +96,7 @@ static void *rlc_data_req_thread(void *_)
{
int i;
pthread_setname_np(pthread_self(), "RLC queue");
while (1) {
if (pthread_mutex_lock(&q.m) != 0) abort();
while (q.length == 0)
@@ -203,6 +208,7 @@ static void *enb_tun_read_thread(void *_)
protocol_ctxt_t ctxt;
int rb_id = 1;
pthread_setname_np( pthread_self(),"enb_tun_read");
while (1) {
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
@@ -247,7 +253,7 @@ static void *ue_tun_read_thread(void *_)
protocol_ctxt_t ctxt;
int rb_id = 1;
pthread_setname_np( pthread_self(),"ue_tun_read");
while (1) {
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
if (len == -1) {
@@ -368,7 +374,7 @@ uint64_t pdcp_module_init(uint64_t _pdcp_optmask)
nas_getparams();
if(UE_NAS_USE_TUN) {
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1;
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1;
netlink_init_tun("ue",num_if);
//Add --nr-ip-over-lte option check for next line
if (IS_SOFTMODEM_NOS1)
@@ -922,6 +922,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity,
*/
ret.sn_start = entity->rx_next;
ret.so_start = 0;
ret.next = cur;
goto set_end_different_sdu;
}
}
+1 -1
View File
@@ -324,7 +324,7 @@ static const struct net_device_ops nasmesh_netdev_ops = {
.ndo_set_mac_address = NULL,
.ndo_set_config = nas_set_config,
.ndo_do_ioctl = nas_CTL_ioctl,
#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1797)
#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1797 && LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0))
.extended.ndo_change_mtu = nas_change_mtu,
#else
.ndo_change_mtu = nas_change_mtu,
-12
View File
@@ -287,18 +287,6 @@ ue_ip_common_ip2wireless(
printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, dst_addr[0],dst_addr[1],dst_addr[2],dst_addr[3]);
}
// modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator start
#ifdef UESIM_EXPANSION
if ((src_addr[3] - 2)> instP) {
pdcph.inst = src_addr[3] - 2;
printk("[UE_IP_DRV] change INST from %d to %d\n",instP, pdcph.inst);
instP = src_addr[3] - 2;
priv_p=netdev_priv(ue_ip_dev[instP]);
}
#endif
// modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator end
//get Ipv4 address and pass to PCDP header
printk("[UE_IP_DRV] source Id: 0x%08x\n",pdcph.sourceL2Id );
printk("[UE_IP_DRV] destinationL2Id Id: 0x%08x\n",pdcph.destinationL2Id );
+38
View File
@@ -79,6 +79,44 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) {
}
void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10) {
int num_ucis = UL_info->uci_ind.num_ucis;
nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list;
for (int i = 0; i < num_ucis; i++) {
switch (uci_list[i].pdu_type) {
case NFAPI_NR_UCI_PUSCH_PDU_TYPE: break;
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1;
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30);
if( (uci_pdu->pduBitmap>>1) & 0x01)
nr_rx_acknack(NULL,uci_pdu,NULL,UL_info,sched_ctrl,stats);
break;
}
case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: {
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4;
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30);
if( (uci_pdu->pduBitmap>>1) & 0x01)
nr_rx_acknack(NULL,NULL,uci_pdu,UL_info,sched_ctrl,stats);
break;
}
}
}
UL_info->uci_ind.num_ucis = 0;
}
void handle_nr_ulsch(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) {
if(nfapi_mode == 1) {
-11
View File
@@ -203,17 +203,6 @@ typedef struct IF_Module_s{
pthread_mutex_t if_mutex;
} IF_Module_t;
// These mutex is used for multiple UEs L2 FAPI simulator.
// Each UEs set these value in UL and UL_INFO is shared in all UE's thread.
typedef struct {
pthread_mutex_t rx_mutex;
pthread_mutex_t crc_mutex;
pthread_mutex_t sr_mutex;
pthread_mutex_t harq_mutex;
pthread_mutex_t cqi_mutex;
pthread_mutex_t rach_mutex;
} FILL_UL_INFO_MUTEX_t;
/*Initial */
IF_Module_t *IF_Module_init(int Mod_id);
void IF_Module_kill(int Mod_id);
-24
View File
@@ -64,8 +64,6 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,
nfapi_rx_indication_pdu_t *pdu;
int timing_advance_update;
pthread_mutex_lock(&fill_ul_mutex.rx_mutex);
UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe;
UL_INFO->rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
UL_INFO->rx_ind.vendor_extension = ul_config_req->vendor_extension;
@@ -101,7 +99,6 @@ void fill_rx_indication_UE_MAC(module_id_t Mod_id,
UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe;
pthread_mutex_unlock(&fill_ul_mutex.rx_mutex);
}
void fill_sr_indication_UE_MAC(int Mod_id,
@@ -109,8 +106,6 @@ void fill_sr_indication_UE_MAC(int Mod_id,
int subframe,
UL_IND_t *UL_INFO,
uint16_t rnti) {
pthread_mutex_lock(&fill_ul_mutex.sr_mutex);
nfapi_sr_indication_t *sr_ind = &UL_INFO->sr_ind;
nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body;
nfapi_sr_indication_pdu_t *pdu = &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs];
@@ -139,7 +134,6 @@ void fill_sr_indication_UE_MAC(int Mod_id,
// UL_INFO->rx_ind.rx_indication_body.number_of_pdus++;
sr_ind_body->number_of_srs++;
pthread_mutex_unlock(&fill_ul_mutex.sr_mutex);
}
void fill_crc_indication_UE_MAC(int Mod_id,
@@ -149,8 +143,6 @@ void fill_crc_indication_UE_MAC(int Mod_id,
uint8_t crc_flag,
int index,
uint16_t rnti) {
pthread_mutex_lock(&fill_ul_mutex.crc_mutex);
nfapi_crc_indication_pdu_t *pdu =
&UL_INFO->crc_ind.crc_indication_body
.crc_pdu_list[UL_INFO->crc_ind.crc_indication_body.number_of_crcs];
@@ -174,8 +166,6 @@ void fill_crc_indication_UE_MAC(int Mod_id,
__FUNCTION__,
pdu->rx_ue_information.rnti,
UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
pthread_mutex_unlock(&fill_ul_mutex.crc_mutex);
}
void fill_rach_indication_UE_MAC(int Mod_id,
@@ -184,10 +174,6 @@ void fill_rach_indication_UE_MAC(int Mod_id,
UL_IND_t *UL_INFO,
uint8_t ra_PreambleIndex,
uint16_t ra_RNTI) {
LOG_D(MAC, "fill_rach_indication_UE_MAC 1 \n");
pthread_mutex_lock(&fill_ul_mutex.rach_mutex);
UL_INFO->rach_ind.rach_indication_body.number_of_preambles = 1;
UL_INFO->rach_ind.header.message_id = NFAPI_RACH_INDICATION;
@@ -232,8 +218,6 @@ void fill_rach_indication_UE_MAC(int Mod_id,
// should call it when we merge with that branch.
oai_nfapi_rach_ind(&UL_INFO->rach_ind);
free(UL_INFO->rach_ind.rach_indication_body.preamble_list);
pthread_mutex_unlock(&fill_ul_mutex.rach_mutex);
}
void fill_ulsch_cqi_indication_UE_MAC(int Mod_id,
@@ -241,7 +225,6 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id,
uint8_t subframe,
UL_IND_t *UL_INFO,
uint16_t rnti) {
pthread_mutex_lock(&fill_ul_mutex.cqi_mutex);
nfapi_cqi_indication_pdu_t *pdu =
&UL_INFO->cqi_ind.cqi_indication_body
.cqi_pdu_list[UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis];
@@ -275,7 +258,6 @@ void fill_ulsch_cqi_indication_UE_MAC(int Mod_id,
raw_pdu->pdu[0] = cqi << 4;
UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis++;
pthread_mutex_unlock(&fill_ul_mutex.cqi_mutex);
}
void fill_ulsch_harq_indication_UE_MAC(
@@ -285,8 +267,6 @@ void fill_ulsch_harq_indication_UE_MAC(
UL_IND_t *UL_INFO,
nfapi_ul_config_ulsch_harq_information *harq_information,
uint16_t rnti) {
pthread_mutex_lock(&fill_ul_mutex.harq_mutex);
nfapi_harq_indication_pdu_t *pdu =
&UL_INFO->harq_ind.harq_indication_body.harq_pdu_list
[UL_INFO->harq_ind.harq_indication_body.number_of_harqs];
@@ -318,7 +298,6 @@ void fill_ulsch_harq_indication_UE_MAC(
}
UL_INFO->harq_ind.harq_indication_body.number_of_harqs++;
pthread_mutex_unlock(&fill_ul_mutex.harq_mutex);
}
void fill_uci_harq_indication_UE_MAC(int Mod_id,
@@ -327,8 +306,6 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
UL_IND_t *UL_INFO,
nfapi_ul_config_harq_information *harq_information,
uint16_t rnti) {
pthread_mutex_lock(&fill_ul_mutex.harq_mutex);
nfapi_harq_indication_t *ind = &UL_INFO->harq_ind;
nfapi_harq_indication_body_t *body = &ind->harq_indication_body;
nfapi_harq_indication_pdu_t *pdu =
@@ -410,7 +387,6 @@ void fill_uci_harq_indication_UE_MAC(int Mod_id,
LOG_D(PHY,
"Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n",
UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
pthread_mutex_unlock(&fill_ul_mutex.harq_mutex);
}
void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id,
-2
View File
@@ -17,8 +17,6 @@
//#include "openair1/PHY/defs.h"
//#include "openair1/PHY/LTE_TRANSPORT/defs.h"
// this mutex is used to set multiple UE's UL value in L2 FAPI simulator.
FILL_UL_INFO_MUTEX_t fill_ul_mutex;
//below 2 difinitions move to phy_stub_UE.c to add initialization when difinition.
extern UL_IND_t *UL_INFO;
extern nfapi_tx_request_pdu_t* tx_request_pdu_list;
+11 -3
View File
@@ -3295,7 +3295,10 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.present = LTE_MTC_SSB_NR_r15__periodicityAndOffset_r15_PR_sf20_r15;
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.choice.sf20_r15 = 0;
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.ssb_Duration_r15 = LTE_MTC_SSB_NR_r15__ssb_Duration_r15_sf4;
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz30;
if (rrc_inst->nr_scg_ssb_freq > 2016666) //FR2
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz120;
else
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz30;
MeasObj2->measObject.choice.measObjectNR_r15.quantityConfigSet_r15 = 1;
MeasObj2->measObject.choice.measObjectNR_r15.ext1 = calloc(1, sizeof(struct LTE_MeasObjectNR_r15__ext1));
@@ -3306,7 +3309,11 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t
if (MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15 == NULL) exit(1);
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->present = LTE_MeasObjectNR_r15__ext1__bandNR_r15_PR_setup;
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 78;
if (rrc_inst->nr_scg_ssb_freq > 2016666) //FR2
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 261;
else
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 78;
ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj2);
}
@@ -4020,7 +4027,6 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0;
MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1;
MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6;
//<<<<<<< HEAD
MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB
if (rrc_inst->carrier[0].sib1->tdd_Config!=NULL) {
@@ -4635,6 +4641,7 @@ rrc_eNB_process_MeasurementReport(
case 7:
LOG_D(RRC, "NR event frame %d subframe %d\n", ctxt_pP->frame, ctxt_pP->subframe);
printf("NR event frame %d subframe %d\n", ctxt_pP->frame, ctxt_pP->subframe);
break;
default:
@@ -7884,6 +7891,7 @@ rrc_eNB_decode_dcch(
if(ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.criticalExtensions.choice.rrcConnectionReconfigurationComplete_r8.
nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
->scg_ConfigResponseNR_r15!=NULL) {
dedicated_DRB = -1; /* put a value that does not run anything below */
ue_context_p->ue_context.Status = RRC_NR_NSA_RECONFIGURED;
/*Trigger E-RAB Modification Indication */
rrc_eNB_send_E_RAB_Modification_Indication(ctxt_pP, ue_context_p);
+7 -1
View File
@@ -88,6 +88,12 @@ int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP,
}
/* TODO BCCH SIB1 SIBs */
if ((Srb_id & RAB_OFFSET ) == BCCH) {
memcpy(&buffer_pP[0],
RC.rrc[Mod_idP]->carrier[CC_id].SIB1_MBMS,
RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_MBMS);
}
/* CCCH */
if( (Srb_id & RAB_OFFSET ) == CCCH) {
@@ -114,4 +120,4 @@ int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP,
return(0);
}
}
+31 -30
View File
@@ -200,6 +200,10 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) {
mib->message.choice.mib->spare.bits_unused = 7; // This makes a spare of 1 bits
mib->message.choice.mib->ssb_SubcarrierOffset = (carrier->ssb_SubcarrierOffset)&15;
/*
* The SIB1 will be sent in this allocation (Type0-PDCCH) : 38.213, 13-4 Table and 38.213 13-11 to 13-14 tables
* the reverse allocation is in nr_ue_decode_mib()
*/
mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero;
mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero;
AssertFatal(scc->ssbSubcarrierSpacing != NULL, "scc->ssbSubcarrierSpacing is null\n");
@@ -265,10 +269,6 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
gNB_RrcConfigurationReq *configuration
) {
asn_enc_rval_t enc_rval;
NR_BCCH_DL_SCH_Message_t *sib1_message ;
struct NR_SIB1 *sib1 ;
int i;
struct NR_PLMN_IdentityInfo nr_plmn_info;
// TODO : Add support for more than one PLMN
//int num_plmn = configuration->num_plmn;
@@ -276,31 +276,29 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
struct NR_PLMN_Identity nr_plmn[num_plmn];
NR_MCC_MNC_Digit_t nr_mcc_digit[num_plmn][3];
NR_MCC_MNC_Digit_t nr_mnc_digit[num_plmn][3];
memset(nr_plmn,0,sizeof(nr_plmn));
memset(nr_mcc_digit,0,sizeof(nr_mcc_digit));
memset(nr_mnc_digit,0,sizeof(nr_mnc_digit));
// struct NR_UAC_BarringInfoSet nr_uac_BarringInfoSet;
sib1_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t));
memset(sib1_message,0,sizeof(NR_BCCH_DL_SCH_Message_t));
NR_BCCH_DL_SCH_Message_t *sib1_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t));
carrier->siblock1 = sib1_message;
sib1_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1;
sib1_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1));
memset(sib1_message->message.choice.c1,0,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1));
sib1_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1;
sib1_message->message.choice.c1->choice.systemInformationBlockType1 = CALLOC(1,sizeof(struct NR_SIB1));
sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1;
memset(sib1,0,sizeof(struct NR_SIB1));
struct NR_SIB1 *sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1;
sib1->cellSelectionInfo = CALLOC(1,sizeof(struct NR_SIB1__cellSelectionInfo));
memset(sib1->cellSelectionInfo,0,sizeof(struct NR_SIB1__cellSelectionInfo));
sib1->cellSelectionInfo->q_RxLevMin = -50;
memset(&nr_plmn_info.plmn_IdentityList,0,sizeof(struct NR_PLMN_IdentityInfo__plmn_IdentityList));
asn_set_empty(&nr_plmn_info.plmn_IdentityList.list);
memset(&nr_plmn_info,0,sizeof(struct NR_PLMN_IdentityInfo));
memset(nr_plmn,0,num_plmn*sizeof(struct NR_PLMN_Identity));
for (i = 0; i < num_plmn; ++i) {
struct NR_PLMN_IdentityInfo *nr_plmn_info=CALLOC(1,sizeof(struct NR_PLMN_IdentityInfo));
asn_set_empty(&nr_plmn_info->plmn_IdentityList.list);
for (int i = 0; i < num_plmn; ++i) {
nr_mcc_digit[i][0] = (configuration->mcc[i]/100)%10;
nr_mcc_digit[i][1] = (configuration->mcc[i]/10)%10;
nr_mcc_digit[i][2] = (configuration->mcc[i])%10;
nr_plmn[i].mcc = CALLOC(1,sizeof(struct NR_MCC));
memset(nr_plmn[i].mcc,0,sizeof(struct NR_MCC));
asn_set_empty(&nr_plmn[i].mcc->list);
ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][0]);
ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][1]);
@@ -308,26 +306,23 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
nr_mnc_digit[i][0] = (configuration->mnc[i]/100)%10;
nr_mnc_digit[i][1] = (configuration->mnc[i]/10)%10;
nr_mnc_digit[i][2] = (configuration->mnc[i])%10;
memset(&nr_plmn[i].mnc,0,sizeof(NR_MNC_t));
nr_plmn[i].mnc.list.size=0;
nr_plmn[i].mnc.list.count=0;
ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][0]);
ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][1]);
ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][2]);
ASN_SEQUENCE_ADD(&nr_plmn_info.plmn_IdentityList.list, &nr_plmn[i]);
ASN_SEQUENCE_ADD(&nr_plmn_info->plmn_IdentityList.list, &nr_plmn[i]);
}//end plmn loop
nr_plmn_info.cellIdentity.buf = MALLOC(8);
memset(nr_plmn_info.cellIdentity.buf,0,8);
nr_plmn_info.cellIdentity.buf[0]= (configuration->cell_identity >> 20) & 0xff;
nr_plmn_info.cellIdentity.buf[1]= (configuration->cell_identity >> 12) & 0xff;
nr_plmn_info.cellIdentity.buf[2]= (configuration->cell_identity >> 4) & 0xff;
nr_plmn_info.cellIdentity.buf[3]= (configuration->cell_identity << 4) & 0xff;
nr_plmn_info.cellIdentity.size= 4;
nr_plmn_info.cellIdentity.bits_unused= 4;
nr_plmn_info.cellReservedForOperatorUse = 0;
memset(&sib1->cellAccessRelatedInfo,0,sizeof(NR_CellAccessRelatedInfo_t));
ASN_SEQUENCE_ADD(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list, &nr_plmn_info);
nr_plmn_info->cellIdentity.buf = CALLOC(1,8);
nr_plmn_info->cellIdentity.buf[0]= (configuration->cell_identity >> 20) & 0xff;
nr_plmn_info->cellIdentity.buf[1]= (configuration->cell_identity >> 12) & 0xff;
nr_plmn_info->cellIdentity.buf[2]= (configuration->cell_identity >> 4) & 0xff;
nr_plmn_info->cellIdentity.buf[3]= (configuration->cell_identity << 4) & 0xff;
nr_plmn_info->cellIdentity.size= 4;
nr_plmn_info->cellIdentity.bits_unused= 4;
nr_plmn_info->cellReservedForOperatorUse = 0;
ASN_SEQUENCE_ADD(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list, nr_plmn_info);
#if 0
sib1->uac_BarringInfo = CALLOC(1, sizeof(struct NR_SIB1__uac_BarringInfo));
memset(sib1->uac_BarringInfo, 0, sizeof(struct NR_SIB1__uac_BarringInfo));
@@ -340,11 +335,12 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
ASN_SEQUENCE_ADD(&sib1->uac_BarringInfo->uac_BarringInfoSetList, &nr_uac_BarringInfoSet);
#endif
//encode SIB1 to data
carrier->SIB1=(uint8_t *) malloc16(128);
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message,
NULL,
(void *)sib1_message,
carrier->SIB1,
100);
128);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
@@ -578,3 +574,8 @@ void do_SpCellConfig(gNB_RRC_INST *rrc,
spconfig->reconfigurationWithSync = CALLOC(1,sizeof(struct NR_ReconfigurationWithSync));
}
int do_DLInformationTransfer_NR (void * p) {
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
/*
* 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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* 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
*/
#include <openair2/RRC/LTE/MESSAGES/asn1_msg.h>
#include <openair2/RRC/NR/nr_rrc_proto.h>
void rrc_gNB_process_NGAP_DOWNLINK_NAS (void ) {
do_DLInformationTransfer(0,NULL,0,0,NULL);
// send it as DL data
/*
rrc_data_req (
&ctxt,
srb_id,
(*rrc_eNB_mui)++,
SDU_CONFIRM_NO,
length,
buffer,
PDCP_TRANSMISSION_MODE_CONTROL);
*/
}
void rrc_gNB_send_NGAP_NAS_FIRST_REQ(void ) {
// We are noCore only now
// create message that should come from 5GC
// send it dow
rrc_gNB_process_NGAP_DOWNLINK_NAS();
}
void nr_rrc_rx_tx() {
// check timers
// check if UEs are lost, to remove them from upper layers
//
}
+1 -1
View File
@@ -93,7 +93,7 @@ int generate_CG_Config(gNB_RRC_INST *rrc,
int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m);
void nr_rrc_rx_tx(void);
/**\brief RRC eNB task.
\param void *args_p Pointer on arguments to start the task. */
+8 -4
View File
@@ -82,6 +82,7 @@
#include "executables/softmodem-common.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair2/X2AP/x2ap_eNB.h>
//#define XER_PRINT
@@ -178,10 +179,11 @@ void rrc_gNB_generate_SgNBAdditionRequestAcknowledge(
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
static void init_NR_SI(gNB_RRC_INST *rrc) {
static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration) {
LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__);
rrc->carrier.MIB = (uint8_t *) malloc16(4);
rrc->carrier.sizeof_MIB = do_MIB_NR(rrc,0);
rrc->carrier.sizeof_SIB1 = do_SIB1_NR(&rrc->carrier,configuration);
LOG_I(NR_RRC,"Done init_NR_SI\n");
rrc_mac_config_req_gNB(rrc->module_id,
rrc->carrier.ssb_SubcarrierOffset,
@@ -271,7 +273,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu
rrc->carrier.pucch_TargetSNRx10 = configuration->pucch_TargetSNRx10;
/// System Information INIT
LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt));
init_NR_SI(rrc);
init_NR_SI(rrc, configuration);
rrc_init_nr_global_param();
openair_nr_rrc_on(&ctxt);
return 0;
@@ -317,8 +319,10 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
MessageDef *msg;
/* send a tick to x2ap */
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS);
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg);
if (is_x2ap_enabled()){
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS);
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg);
}
}
///---------------------------------------------------------------------------------------------------------------///
File diff suppressed because it is too large Load Diff
+1 -16
View File
@@ -6,6 +6,7 @@
#include <arpa/inet.h>
#define MAC_LTE_DLT 147
#define DLT_IPV4 228
/********************************************************/
/* Definitions and descriptions come from:
http://wiki.wireshark.org/Development/LibpcapFileFormat */
@@ -29,20 +30,4 @@ typedef struct pcaprec_hdr_s {
unsigned int orig_len; /* actual length of packet */
} pcaprec_hdr_t;
/* Context information for every MAC PDU that will be logged */
typedef struct MAC_Context_Info_t {
unsigned short radioType;
unsigned char direction;
unsigned char rntiType;
unsigned short rnti;
unsigned short ueid;
unsigned char isRetx;
unsigned char crcStatusOK;
unsigned short sysFrameNumber;
unsigned short subFrameNumber;
unsigned int subframesSinceCaptureStart;
} MAC_Context_Info_t;
#endif
+1 -1
View File
@@ -73,7 +73,7 @@ typedef guint8 gboolean;
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*---------------------------------------------------------------------------------------------------------------------------------------------*/
#define OPT_PARAMS_DESC { \
{"type" , CONFIG_HLP_TYPEMON, 0, strptr:&in_type, defstrval:"none", TYPE_STRING, 0}, \
{"type" , CONFIG_HLP_TYPEMON, 0, strptr:(char**)&in_type, defstrval:"none", TYPE_STRING, 0}, \
{"ip" , CONFIG_HLP_L2MONIP, 0, strptr:(char**)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, 0}, \
{"path" , CONFIG_HLP_L2MONPATH, 0, strptr:(char**)&in_path,defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, 0}, \
}
+108 -107
View File
@@ -90,6 +90,7 @@ what about the implementation
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
#include "common/config/config_userapi.h"
#include "opt.h"
#include "common/utils/system.h"
@@ -99,8 +100,6 @@ int opt_enabled=0;
//static unsigned char g_PDUBuffer[1600];
//static unsigned int g_PDUOffset;
static char in_ip[128]={0};
static char in_path[128]={0};
FILE *file_fd = NULL;
pcap_hdr_t file_header = {
0xa1b2c3d4, /* magic number */
@@ -108,10 +107,14 @@ pcap_hdr_t file_header = {
0, /* timezone */
0, /* sigfigs - apparently all tools do this */
65535, /* snaplen - this should be long enough */
MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
DLT_IPV4
//MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
};
trace_mode_t opt_type = OPT_NONE;
static char *in_type=NULL;
static char *in_path=NULL;
static char *in_ip=NULL;
static unsigned int subframesSinceCaptureStart;
static int g_socksd = -1;/* UDP socket used for sending frames */
@@ -131,8 +134,80 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
guint8 oob_event, guint8 oob_event_value,
uint8_t *pdu_buffer, unsigned int pdu_buffer_size);
static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
const unsigned char *PDU, unsigned int length);
unsigned short checksum(unsigned short *ptr, int length) {
int sum = 0;
u_short answer = 0;
unsigned short *w = ptr;
int nleft = length;
while(nleft > 1) {
sum += *w++;
nleft -= 2;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
static int MAC_LTE_PCAP_WritePDU(const uint8_t *PDU,
unsigned int length) {
pcaprec_hdr_t packet_header;
// IPv4 header
typedef struct ip_hdr {
unsigned char ip_verlen; // 4-bit IPv4 version 4-bit header length (in 32-bit words)
unsigned char ip_tos; // IP type of service
unsigned short ip_totallength; // Total length
unsigned short ip_id; // Unique identifier
unsigned short ip_offset; // Fragment offset field
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
// Define the UDP header
typedef struct udp_hdr {
unsigned short src_portno; // Source port no.
unsigned short dst_portno; // Dest. port no.
unsigned short udp_length; // Udp packet length
unsigned short udp_checksum; // Udp checksum (optional)
} UDP_HDR;
IPV4_HDR IPheader= {0};
IPheader.ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(uint32_t));
IPheader.ip_totallength = htons(sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length);
IPheader.ip_ttl = 8; // Time-to-live is eight
IPheader.ip_protocol = IPPROTO_UDP;
IPheader.ip_srcaddr = inet_addr(in_ip);
IPheader.ip_destaddr = inet_addr(in_ip);
IPheader.ip_checksum = checksum((unsigned short *)&IPheader, sizeof(IPV4_HDR));
// Initialize the UDP header
UDP_HDR UDPheader;
UDPheader.src_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT);
UDPheader.dst_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT);
UDPheader.udp_length = htons(sizeof(UDP_HDR) + length);
UDPheader.udp_checksum = 0;
/****************************************************************/
/* PCAP Header */
/* TODO: Timestamp might want to be relative to a more sensible
base time... */
struct timeval tv;
gettimeofday(&tv, NULL);
packet_header.ts_sec = tv.tv_sec;
packet_header.ts_usec = tv.tv_usec;
packet_header.incl_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length;
packet_header.orig_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length;
/***************************************************************/
/* Now write everything to the file */
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd);
fwrite(&IPheader, sizeof(IPV4_HDR), 1, file_fd);
fwrite(&UDPheader, sizeof(UDP_HDR), 1, file_fd);
fwrite(PDU, 1, length, file_fd);
fflush(file_fd);
return length;
}
static void *opt_listener_thread(void *arg) {
ssize_t ret;
@@ -198,7 +273,6 @@ int opt_create_listener_socket(char *ip_address, uint16_t port) {
}
threadCreate(&opt_listener.thread, opt_listener_thread, NULL, "flexran", -1, OAI_PRIORITY_RT_LOW);
return 0;
}
@@ -321,67 +395,20 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
frameOffset += pdu_buffer_size;
}
/* Send out the data over the UDP socket */
bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0,
(const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr));
if ( opt_type == OPT_WIRESHARK )
/* Send out the data over the UDP socket */
bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0,
(const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr));
else
bytesSent = MAC_LTE_PCAP_WritePDU(frameBuffer, frameOffset);
if (bytesSent != frameOffset) {
LOG_W(OPT, "sendto() failed (not a thread-safe func)- expected %d bytes, got %ld (errno=%d)\n",
LOG_W(OPT, "trace_pdu expected %d bytes, got %ld (errno=%d)\n",
frameOffset, bytesSent, errno);
//exit(1);
}
}
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
const uint8_t *PDU,
unsigned int length)
{
pcaprec_hdr_t packet_header;
uint8_t context_header[256];
int offset = 0;
unsigned short tmp16;
/*****************************************************************/
/* Context information (same as written by UDP heuristic clients */
context_header[offset++] = context->radioType;
context_header[offset++] = context->direction;
context_header[offset++] = context->rntiType;
/* RNTI */
context_header[offset++] = MAC_LTE_RNTI_TAG;
tmp16 = htons(context->rnti);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* UEId */
context_header[offset++] = MAC_LTE_UEID_TAG;
tmp16 = htons(context->ueid);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* Subframe number */
context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
tmp16 = htons(context->subFrameNumber);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* CRC Status */
context_header[offset++] = MAC_LTE_CRC_STATUS_TAG;
context_header[offset++] = context->crcStatusOK;
/* Data tag immediately preceding PDU */
context_header[offset++] = MAC_LTE_PAYLOAD_TAG;
/****************************************************************/
/* PCAP Header */
/* TODO: Timestamp might want to be relative to a more sensible
base time... */
packet_header.ts_sec = context->subframesSinceCaptureStart / 1000;
packet_header.ts_usec = (context->subframesSinceCaptureStart % 1000) * 1000;
packet_header.incl_len = offset + length;
packet_header.orig_len = offset + length;
/***************************************************************/
/* Now write everything to the file */
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd);
fwrite(context_header, 1, offset, file_fd);
fwrite(PDU, 1, length, file_fd);
return 1;
}
#include <common/ran_context.h>
extern RAN_CONTEXT_t RC;
#include <openair1/PHY/phy_extern_ue.h>
@@ -389,7 +416,6 @@ extern RAN_CONTEXT_t RC;
void trace_pdu_implementation(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
int ueid, int rntiType, int rnti, uint16_t sysFrameNumber, uint8_t subFrameNumber, int oob_event,
int oob_event_value) {
MAC_Context_Info_t pdu_context;
int radioType=FDD_RADIO;
LOG_D(OPT,"sending packet to wireshark: direction=%s, size: %d, ueid: %d, rnti: %x, frame/sf: %d.%d\n",
direction?"DL":"UL", pdu_buffer_size, ueid, rnti, sysFrameNumber,subFrameNumber);
@@ -405,53 +431,41 @@ void trace_pdu_implementation(int direction, uint8_t *pdu_buffer, unsigned int p
switch (opt_type) {
case OPT_WIRESHARK :
if (g_socksd == -1) {
if (g_socksd == -1)
return;
}
SendFrame( radioType,
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
oob_event,oob_event_value,
pdu_buffer, pdu_buffer_size);
break;
case OPT_PCAP:
if (file_fd == NULL) {
if (file_fd == NULL)
return;
}
pdu_context.radioType = radioType;
pdu_context.direction = (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK
: DIRECTION_UPLINK;
pdu_context.rntiType = rntiType;
pdu_context.rnti = rnti;
pdu_context.ueid = ueid;
pdu_context.isRetx = 0;
pdu_context.crcStatusOK =1;
pdu_context.sysFrameNumber = sysFrameNumber;
pdu_context.subFrameNumber = subFrameNumber;
pdu_context.subframesSinceCaptureStart = subframesSinceCaptureStart++;
MAC_LTE_PCAP_WritePDU( &pdu_context, pdu_buffer, pdu_buffer_size);
break;
case OPT_TSHARK:
default:
return;
break;
}
SendFrame( radioType,
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
oob_event,oob_event_value,
pdu_buffer, pdu_buffer_size);
}
/*---------------------------------------------------*/
int init_opt(void)
{
char *in_type=NULL;
int init_opt(void) {
in_type=malloc(200);
in_ip=malloc(200);
in_path=malloc(200);
paramdef_t opt_params[] = OPT_PARAMS_DESC ;
checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC;
uint16_t in_port=0;
config_set_checkfunctions(opt_params, opt_checkParams,
sizeof(opt_params)/sizeof(paramdef_t));
config_get( opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX);
subframesSinceCaptureStart = 0;
int tmptype = config_get_processedint( &(opt_params[OPTTYPE_IDX]));
@@ -462,25 +476,21 @@ int init_opt(void)
} else if (tmptype == OPT_PCAP && strlen(in_path) > 0) {
opt_type = OPT_PCAP;
opt_enabled=1;
LOG_I(OPT,"Enabling OPT for PCAP with the following file %s \n",in_path);
} else if (tmptype == OPT_WIRESHARK && strlen(in_ip) > 0) {
opt_enabled=1;
opt_type = OPT_WIRESHARK;
LOG_I(OPT,"Enabling OPT for wireshark for local interface %s\n",in_ip);
} else {
LOG_E(OPT,"Invalid OPT configuration\n");
config_printhelp(opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX);
}
in_port = PACKET_MAC_LTE_DEFAULT_UDP_PORT;
// trace_mode
switch (opt_type) {
case OPT_WIRESHARK:
LOG_I(OPT,"mode Wireshark: ip %s port %d\n", in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT);
/* Create local server socket only if using localhost address */
if (strcmp(in_ip, "127.0.0.1") == 0) {
opt_create_listener_socket(in_ip, in_port);
if (strncmp(in_ip, "127.0.0.1", 4) == 0) {
opt_create_listener_socket(in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT);
}
g_socksd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -493,11 +503,12 @@ int init_opt(void)
/* Get remote IP address from the function argument */
g_serv_addr.sin_family = AF_INET;
g_serv_addr.sin_port = htons(in_port);
g_serv_addr.sin_port = htons(PACKET_MAC_LTE_DEFAULT_UDP_PORT);
g_serv_addr.sin_addr.s_addr = inet_addr(in_ip);
break;
case OPT_PCAP:
LOG_I(OPT,"mode PCAB : path is %s \n",in_path);
file_fd = fopen(in_path, "w");
if (file_fd == NULL) {
@@ -516,19 +527,9 @@ int init_opt(void)
default:
opt_type = OPT_NONE;
LOG_W(OPT, "supported Option\n");
LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type);
break;
}
if ( opt_type == OPT_WIRESHARK )
LOG_E(OPT,"mode Wireshark: ip %s port %d\n", in_ip, in_port);
else if (opt_type == OPT_PCAP)
LOG_E(OPT,"mode PCAB : path is %s \n",in_path);
else
LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type);
// mac_info = (mac_info*)malloc16(sizeof(mac_lte_info));
// memset(mac_info, 0, sizeof(mac_lte_info)+pdu_buffer_size + 8);
return (1);
}