diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index a0a43b6d7951ea3f4eb9fa1cebb9aa2dad5e34d7..d0b71157af05a33f0b6ec6d13ca02a9214e376d9 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -71,6 +71,10 @@ #include "SCellToAddMod-r10.h" #endif +#ifdef FAPI +#include "ff-mac.h" +#endif + //#ifdef PHY_EMUL //#include "SIMULATION/PHY_EMULATION/impl_defs.h" //#endif @@ -910,6 +914,10 @@ typedef struct { /// processing time of eNB ULSCH reception time_stats_t rx_ulsch_sdu; // include rlc_data_ind +#ifdef FAPI + /// fapi interface handler + fapi_interface_t *fapi; +#endif } eNB_MAC_INST; /* diff --git a/openair2/LAYER2/MAC/ff-mac.c b/openair2/LAYER2/MAC/ff-mac.c index 1dedf8cbb4641199a56074feac90f818eda565da..c05fb5e261de8988684542d0df018c7f87c6008c 100644 --- a/openair2/LAYER2/MAC/ff-mac.c +++ b/openair2/LAYER2/MAC/ff-mac.c @@ -3,60 +3,209 @@ #include "ff-mac-csched-sap.h" #include "ff-mac-init.h" #include "log.h" +#include "assertions.h" + +#undef LOG_D +#define LOG_D LOG_I #include <stdlib.h> +#include <pthread.h> + +/* number of callbacks */ +#define N 9 /* this structure stores required data for OAI to work with FAPI */ /* it is the private version of fapi_interface_t */ struct fapi { fapi_interface_t fi; /* the start of the structure matches fapi_interface_t */ + pthread_mutex_t mutex[N]; + pthread_cond_t cond[N]; + volatile int req_id[N]; + volatile int rsp_id[N]; + struct CschedCellConfigCnfParameters CschedCellConfigCnfParameters; }; -/* here come the callbacks */ +#define LOCK(fi, fn) do { \ + LOG_D(MAC, "%s: locking fn %d fi %p mutex %p\n", __FUNCTION__, fn, fi, &fi->mutex[fn]); \ + if (pthread_mutex_lock(&fi->mutex[fn])) \ + AssertFatal(0, "%s:%d:%s: mutex error\n", __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +#define UNLOCK(fi, fn) do { \ + LOG_D(MAC, "%s: unlocking fn %d fi %p mutex %p\n", __FUNCTION__, fn, fi, &fi->mutex[fn]); \ + if (pthread_mutex_unlock(&fi->mutex[fn])) \ + AssertFatal(0, "%s:%d:%s: mutex error\n", __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +#define CHECK(fi, fn) do { \ + if (fi->req_id[fn] != fi->rsp_id[fn]) \ + AssertFatal(0, "%s:%d:%s: check error\n", __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +#define WAIT(fi, fn) do { \ + LOG_D(MAC, "%s: WAIT fn %d req %d rsp %d\n", __FUNCTION__, fn, fi->req_id[fn], fi->rsp_id[fn]); \ + while (fi->req_id[fn] == fi->rsp_id[fn]) \ + if (pthread_cond_wait(&fi->cond[fn], &fi->mutex[fn])) \ + AssertFatal(0, "%s:%d:%s: cond error\n", __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +#define DONE_callback(fi, fn) do { \ + fi->req_id[fn]++; \ + if (pthread_cond_signal(&fi->cond[fn])) \ + AssertFatal(0, "%s:%d:%s: mutex error\n", __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +#define DONE_wrapper(fi, fn) do { \ + fi->rsp_id[fn]++; \ + } while (0) + +/* SCHED "wrappers" */ + +void SchedDlConfigInd(fapi_interface_t *_fi, struct SchedDlConfigIndParameters *params) +{ + int fn = 0; +} + +void SchedUlConfigInd(fapi_interface_t *_fi, struct SchedUlConfigIndParameters *params) +{ + int fn = 1; +} + +/* CSCHED "wrappers" */ + +void CschedCellConfigCnf(fapi_interface_t *_fi, struct CschedCellConfigCnfParameters *params) +{ + struct fapi *fi = (struct fapi *)_fi; + int fn = 2; + LOG_D(MAC, "CschedCellConfigCnf enter\n"); + + LOCK(fi, fn); + WAIT(fi, fn); + + *params = fi->CschedCellConfigCnfParameters; + + DONE_wrapper(fi, fn); + UNLOCK(fi, fn); + + LOG_D(MAC, "CschedCellConfigCnf leave\n"); +} + +void CschedUeConfigCnf(fapi_interface_t *_fi, struct CschedUeConfigCnfParameters *params) +{ + int fn = 3; +} + +void CschedLcConfigCnf(fapi_interface_t *_fi, struct CschedLcConfigCnfParameters *params) +{ + int fn = 4; +} + +void CschedLcReleaseCnf(fapi_interface_t *_fi, struct CschedLcReleaseCnfParameters *params) +{ + int fn = 5; +} + +void CschedUeReleaseCnf(fapi_interface_t *_fi, struct CschedUeReleaseCnfParameters *params) +{ + int fn = 6; +} + +void CschedUeConfigUpdateInd(fapi_interface_t *_fi, struct CschedUeConfigUpdateIndParameters *params) +{ + int fn = 7; +} + +void CschedCellConfigUpdateInd(fapi_interface_t *_fi, struct CschedCellConfigUpdateIndParameters *params) +{ + int fn = 8; +} + +/* SCHED callbacks */ + void SchedDlConfigInd_callback(void *callback_data, const struct SchedDlConfigIndParameters *params) { + int fn = 0; } void SchedUlConfigInd_callback(void *callback_data, const struct SchedUlConfigIndParameters *params) { + int fn = 1; } +/* CSCHED callbacks */ + void CschedCellConfigCnf_callback(void *callback_data, const struct CschedCellConfigCnfParameters *params) { + struct fapi *fi = callback_data; + int fn = 2; + LOG_D(MAC, "CschedCellConfigCnf_callback enter\n"); + + LOCK(fi, fn); + CHECK(fi, fn); + + fi->CschedCellConfigCnfParameters = *params; + + DONE_callback(fi, fn); + UNLOCK(fi, fn); + + LOG_D(MAC, "CschedCellConfigCnf_callback leave\n"); } void CschedUeConfigCnf_callback(void *callback_data, const struct CschedUeConfigCnfParameters *params) { + int fn = 3; } void CschedLcConfigCnf_callback(void *callback_data, const struct CschedLcConfigCnfParameters *params) { + int fn = 4; } void CschedLcReleaseCnf_callback(void *callback_data, const struct CschedLcReleaseCnfParameters *params) { + int fn = 5; } void CschedUeReleaseCnf_callback(void *callback_data, const struct CschedUeReleaseCnfParameters *params) { + int fn = 6; } void CschedUeConfigUpdateInd_callback(void *callback_data, const struct CschedUeConfigUpdateIndParameters *params) { + int fn = 7; } void CschedCellConfigUpdateInd_callback(void *callback_data, const struct CschedCellConfigUpdateIndParameters *params) { + int fn = 8; } fapi_interface_t *init_fapi(void) { struct fapi *ret; + int i; LOG_I(MAC, "FAPI initialization\n"); ret = calloc(1, sizeof(struct fapi)); - if (ret == NULL) LOG_E(MAC, "init_fapi: memory allocation error\n"); + if (ret == NULL) { + LOG_E(MAC, "init_fapi: memory allocation error\n"); + return NULL; + } + + for (i = 0; i < N; i++) { + if (pthread_mutex_init(&ret->mutex[i], NULL)) { + LOG_E(MAC, "init_fapi: mutex init error\n"); + exit(1); + } + if (pthread_cond_init(&ret->cond[i], NULL)) { + LOG_E(MAC, "init_fapi: cond init error\n"); + exit(1); + } + ret->req_id[i] = 0; + ret->rsp_id[i] = 0; + } ret->fi.sched = SchedInit(ret, SchedDlConfigInd_callback, diff --git a/openair2/LAYER2/MAC/ff-mac.h b/openair2/LAYER2/MAC/ff-mac.h index d3caabd856d102ddab938a36c84e220e4c6fa3d5..55dac78f23bf64ac446e21f3d5043ce1a6d9ba42 100644 --- a/openair2/LAYER2/MAC/ff-mac.h +++ b/openair2/LAYER2/MAC/ff-mac.h @@ -14,4 +14,25 @@ typedef struct { */ fapi_interface_t *init_fapi(void); +/* the following functions are called by OAI + * they wait for the corresponding callback + * to be called by the FAPI scheduler + */ + +#include "ff-mac-sched-sap.h" +#include "ff-mac-csched-sap.h" + +/* from SCHED */ +void SchedDlConfigInd(fapi_interface_t *, struct SchedDlConfigIndParameters* params); +void SchedUlConfigInd(fapi_interface_t *, struct SchedUlConfigIndParameters* params); + +/* from CSCHED */ +void CschedCellConfigCnf(fapi_interface_t *, struct CschedCellConfigCnfParameters *params); +void CschedUeConfigCnf(fapi_interface_t *, struct CschedUeConfigCnfParameters *params); +void CschedLcConfigCnf(fapi_interface_t *, struct CschedLcConfigCnfParameters *params); +void CschedLcReleaseCnf(fapi_interface_t *, struct CschedLcReleaseCnfParameters *params); +void CschedUeReleaseCnf(fapi_interface_t *, struct CschedUeReleaseCnfParameters *params); +void CschedUeConfigUpdateInd(fapi_interface_t *, struct CschedUeConfigUpdateIndParameters *params); +void CschedCellConfigUpdateInd(fapi_interface_t *, struct CschedCellConfigUpdateIndParameters *params); + #endif /* FF_MAC_H */ diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index ef281ee0f68b4e05b7e3415fd9a70c006dbbdc00..df25009529d311899468cbacdfea66c21ddbdb3b 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -352,6 +352,22 @@ int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, ui #endif //end ALU's algo +#ifdef FAPI + /// setup FAPI interface + for (i=0; i<NB_eNB_INST; i++) { + eNB_mac_inst[i].fapi = init_fapi(); + AssertFatal(eNB_mac_inst[i].fapi != NULL, "error calling init_fapi()\n"); + } + + /* test code, to remove */ + struct CschedCellConfigReqParameters p; + struct CschedCellConfigCnfParameters r; + CschedCellConfigReq(eNB_mac_inst[0].fapi->sched, &p); + CschedCellConfigCnf(eNB_mac_inst[0].fapi, &r); + if (r.result != ff_SUCCESS) abort(); + +#endif + LOG_I(MAC,"[MAIN][INIT] Init function finished\n"); return(0); diff --git a/openair2/LAYER2/MAC/minifapi.c b/openair2/LAYER2/MAC/minifapi.c index 6a9d307d55511e981ff9e9bb71e0ef5c34914453..4fb2aec53e3b68c59dc09bb36b8a42a7accc2c9c 100644 --- a/openair2/LAYER2/MAC/minifapi.c +++ b/openair2/LAYER2/MAC/minifapi.c @@ -11,6 +11,8 @@ #include <stdlib.h> #include <stdio.h> +#define LOG(...) do { printf("minifapi:%s:%d: ", __FUNCTION__, __LINE__); printf(__VA_ARGS__); printf("\n"); } while (0) + struct scheduler { void *callback_data; SchedDlConfigInd_callback_t *SchedDlConfigInd; @@ -38,7 +40,7 @@ void *SchedInit( { struct scheduler *ret; - printf("minifapi:%s:%d: start\n", __FUNCTION__, __LINE__); + LOG("enter"); ret = calloc(1, sizeof(struct scheduler)); if (ret == NULL) { @@ -57,7 +59,7 @@ void *SchedInit( ret->CschedUeConfigUpdateInd = CschedUeConfigUpdateInd; ret->CschedCellConfigUpdateInd = CschedCellConfigUpdateInd; - printf("minifapi:%s:%d: done\n", __FUNCTION__, __LINE__); + LOG("leave"); return ret; } @@ -112,6 +114,17 @@ void SchedUlCqiInfoReq(void *_sched, const struct SchedUlCqiInfoReqParameters *p void CschedCellConfigReq(void *_sched, const struct CschedCellConfigReqParameters *params) { + struct scheduler *sched = _sched; + struct CschedCellConfigCnfParameters conf; + + LOG("enter"); + + conf.result = ff_SUCCESS; + conf.nr_vendorSpecificList = 0; + + sched->CschedCellConfigCnf(sched->callback_data, &conf); + + LOG("leave"); } void CschedUeConfigReq(void *_sched, const struct CschedUeConfigReqParameters *params)