diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 197b94699c..6fa30b2b35 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -477,7 +477,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR False "For generating sequenc
add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams")
add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams")
-add_boolean_option(ENB_AGENT True "enable eNB agent to inteface with a SDN contrller")
+add_boolean_option(ENB_AGENT_SB_IF True "enable eNB agent to inteface with a SDN contrller")
########################
# Include order
@@ -693,7 +693,7 @@ include_directories("${OPENAIR_DIR}")
# Utilities Library
################
-if (ENB_AGENT)
+if (ENB_AGENT_SB_IF)
# set the version of protobuf messages, V3 not supported yet
add_list1_option(PRPT_VERSION V2 "PRPT MSG protobuf grammar version" V2 V3)
@@ -730,7 +730,8 @@ if (ENB_AGENT)
${PRPT_source}
)
set(PRPT_MSG_LIB PRPT_MSG)
- include_directories ("${PRPT_C_DIR}")
+ #message("prpt c dir is : ${PRPT_C_DIR}")
+ include_directories (${PRPT_C_DIR})
add_library(ASYNC_IF
${OPENAIR2_DIR}/UTIL/ASYNC_IF/socket_link.c
@@ -740,6 +741,18 @@ if (ENB_AGENT)
set(ASYNC_IF_LIB ASYNC_IF)
include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF)
+ add_library(ENB_AGENT
+ ${OPENAIR2_DIR}/ENB_APP/enb_agent_handler.c
+ ${OPENAIR2_DIR}/ENB_APP/enb_agent_common.c
+ ${OPENAIR2_DIR}/ENB_APP/enb_agent_mac.c
+ ${OPENAIR2_DIR}/ENB_APP/enb_agent.c
+ )
+ set(ENB_AGENT_LIB ENB_AGENT)
+ #include_directories(${OPENAIR2_DIR}/ENB_APP)
+
+ set(PROTOBUF_LIB "protobuf-c")
+
+ #set(PROTOBUF_LIB "protobuf") #for Cpp
endif()
@@ -1647,15 +1660,16 @@ add_executable(oaisim_nos1
target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim_nos1
-Wl,--start-group
- RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB}
+ RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${PRPT_MSG_LIB} ${ASYNC_IF_LIB} ${ENB_AGENT_LIB}
-Wl,--end-group )
target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib}
- ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES})
+ ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB})
#Force link with forms, regardless XFORMS option
target_link_libraries (oaisim_nos1 forms)
+#message("protobuflib is ${PROTOBUF_LIB}")
# Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator
#####################################
diff --git a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
index a905510150..7bdf252352 100644
--- a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
+++ b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.template
@@ -48,7 +48,7 @@ set ( NEW_FFT True )
set ( NO_RRM True )
set ( OAI_EMU True )
set ( OAISIM True )
-set ( OAI_NW_DRIVER_TYPE_ETHERNET True )
+set ( OAI_NW_DRIVER_TYPE_ETHERNET False )
set ( OAI_NW_DRIVER_USE_NETLINK True )
set ( OPENAIR1 True )
set ( OPENAIR2 True )
diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto
index f25613d86d..b2319c8220 100644
--- a/openair2/ENB_APP/MESSAGES/V2/header.proto
+++ b/openair2/ENB_APP/MESSAGES/V2/header.proto
@@ -3,7 +3,7 @@ package protocol;
message prp_header {
optional uint32 version = 1;
optional uint32 type = 2;
- optional uint32 xid = 3;
+ optional uint32 xid = 4;
}
enum prp_type {
@@ -16,3 +16,4 @@ enum prp_type {
PRPT_STATS_REQUEST = 3;
PRPT_STATS_REPLY = 4;
}
+
diff --git a/openair2/ENB_APP/MESSAGES/V2/progran.proto b/openair2/ENB_APP/MESSAGES/V2/progran.proto
index e631762946..363592d6e3 100644
--- a/openair2/ENB_APP/MESSAGES/V2/progran.proto
+++ b/openair2/ENB_APP/MESSAGES/V2/progran.proto
@@ -1,10 +1,12 @@
+//'syntax = "proto2";'
package protocol;
import "stats_messages.proto";
import "header.proto";
message progran_message {
- oneof msg {
+ required progran_direction msg_dir = 100;
+ oneof msg {
prp_hello hello_msg = 1;
prp_echo_request echo_request_msg = 2;
prp_echo_reply echo_reply_msg = 3;
@@ -13,6 +15,32 @@ message progran_message {
}
}
+enum progran_direction {
+ //option allow_alias = true;
+ NOT_SET = 0;
+ INITIATING_MESSAGE = 1;
+ SUCCESSFUL_OUTCOME=2;
+ UNSUCCESSFUL_OUTCOME=3;
+}
+
+enum progran_err {
+ option allow_alias = true;
+ // message errors
+ NO_ERR = 0;
+ MSG_DEQUEUING = -1;
+ MSG_ENQUEUING = -2;
+ MSG_DECODING = -3;
+ MSG_ENCODING = -4;
+ MSG_BUILD = -5;
+ MSG_NOT_SUPPORTED = -6;
+ MSG_NOT_HANDLED = -7;
+ MSG_NOT_VALIDATED = -8;
+ MSG_OUT_DATED = -9;
+
+
+ // other erros
+ UNEXPECTED = -100;
+}
//
// Maintenance and discovery messages
@@ -34,7 +62,6 @@ message prp_echo_reply {
}
-
//
// Statistics request and reply message
//
diff --git a/openair2/ENB_APP/enb_agent.c b/openair2/ENB_APP/enb_agent.c
new file mode 100644
index 0000000000..c9a00ae9ce
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent.c
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+
+#include "enb_agent_common.h"
+#include "link_manager.h"
+#include "log.h"
+#include "enb_agent.h"
+
+typedef uint8_t xid_t;
+
+// tx and rx shared context
+typedef struct {
+ message_queue_t *tx_mq;
+ message_queue_t *rx_mq;
+ xid_t tx_xid;
+ xid_t rx_xid;
+} msg_context_t;
+msg_context_t shared_ctxt;
+
+void *send_thread(void *arg);
+void *receive_thread(void *arg);
+pthread_t new_thread(void *(*f)(void *), void *b);
+
+void *send_thread(void *arg) {
+
+ msg_context_t *d = arg;
+ void *data;
+ int size;
+ int priority;
+
+
+ while (1) {
+ // need logic for the timer, and
+ usleep(10);
+ if (message_put(d->tx_mq, data, size, priority)) goto error;
+ }
+
+ return NULL;
+
+error:
+ printf("receive_thread: there was an error\n");
+ return NULL;
+}
+
+void *receive_thread(void *arg) {
+
+ msg_context_t *d = arg;
+ void *data;
+ int size;
+ int priority;
+ err_code_t err_code;
+
+ Protocol__ProgranMessage *msg;
+
+ while (1) {
+ if (message_get(d->rx_mq, &data, &size, &priority)){
+ err_code = PROTOCOL__PROGRAN_ERR__MSG_DEQUEUING;
+ goto error;
+ }
+ LOG_D(ENB_APP,"received message with size %d\n", size);
+
+
+ msg=enb_agent_handle_message(d->rx_xid, data, size);
+
+ free(data);
+
+ d->rx_xid = ((d->rx_xid)+1)%4;
+ d->tx_xid = d->rx_xid;
+
+ // check if there is something to send back to the controller
+ if (msg != NULL){
+ data=enb_agent_send_message(d->tx_xid,msg,&size);
+
+ if (message_put(d->tx_mq, data, size, priority)){
+ err_code = PROTOCOL__PROGRAN_ERR__MSG_ENQUEUING;
+ goto error;
+ }
+ LOG_D(ENB_APP,"sent message with size %d\n", size);
+ }
+
+ }
+
+ return NULL;
+
+error:
+ printf("receive_thread: error %d occured\n",err_code);
+ return NULL;
+}
+
+
+/* utility function to create a thread */
+pthread_t new_thread(void *(*f)(void *), void *b) {
+ pthread_t t;
+ pthread_attr_t att;
+
+ if (pthread_attr_init(&att)){
+ fprintf(stderr, "pthread_attr_init err\n");
+ exit(1);
+ }
+ if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
+ fprintf(stderr, "pthread_attr_setdetachstate err\n");
+ exit(1);
+ }
+ if (pthread_create(&t, &att, f, b)) {
+ fprintf(stderr, "pthread_create err\n");
+ exit(1);
+ }
+ if (pthread_attr_destroy(&att)) {
+ fprintf(stderr, "pthread_attr_destroy err\n");
+ exit(1);
+ }
+
+ return t;
+}
+
+int enb_agent_start(){
+
+ socket_link_t *link;
+ message_queue_t *send_queue;
+ message_queue_t *receive_queue;
+ link_manager_t *manager;
+
+ LOG_I(ENB_APP,"starting enb agent client\n");
+
+ link = new_link_client("127.0.0.1", 2210);
+ if (link == NULL) goto error;
+
+ send_queue = new_message_queue();
+ if (send_queue == NULL) goto error;
+ receive_queue = new_message_queue();
+ if (receive_queue == NULL) goto error;
+
+ manager = create_link_manager(send_queue, receive_queue, link);
+ if (manager == NULL) goto error;
+
+
+ memset(&shared_ctxt, 0, sizeof(msg_context_t));
+
+ shared_ctxt.tx_mq = send_queue;
+ shared_ctxt.rx_mq = receive_queue;
+
+ new_thread(receive_thread, &shared_ctxt);
+
+ // new_thread(send_thread, &shared_ctxt);
+
+ // while (1) pause();
+
+ printf("client ends\n");
+ return 0;
+
+error:
+ printf("there was an error\n");
+ return 1;
+
+}
+
+
+
+int enb_agent_stop(){
+
+
+}
diff --git a/openair2/ENB_APP/enb_agent.h b/openair2/ENB_APP/enb_agent.h
new file mode 100644
index 0000000000..89d1d9e0c2
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent.h
@@ -0,0 +1,47 @@
+
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef ENB_AGENT_H_
+#define ENB_AGENT_H_
+
+
+int enb_agent_start();
+
+int enb_agent_stop();
+
+
+#endif
diff --git a/openair2/ENB_APP/enb_agent_common.c b/openair2/ENB_APP/enb_agent_common.c
new file mode 100644
index 0000000000..d71a5a6acc
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent_common.c
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+
+#include "enb_agent_common.h"
+#include "log.h"
+
+
+int enb_agent_serialize_message(Protocol__ProgranMessage *msg, void **buf, int *size) {
+
+ *size = protocol__progran_message__get_packed_size(msg);
+
+ *buf = malloc(*size);
+ if (buf == NULL)
+ goto error;
+
+ protocol__progran_message__pack(msg, *buf);
+
+ return 0;
+
+ error:
+ LOG_E(ENB_APP, "an error occured\n"); // change the com
+ return -1;
+}
+
+
+
+/* We assume that the buffer size is equal to the message size.
+ Should be chekced durint Tx/Rx */
+int enb_agent_deserialize_message(void *data, int size, Protocol__ProgranMessage **msg) {
+ *msg = protocol__progran_message__unpack(NULL, size, data);
+ if (*msg == NULL)
+ goto error;
+
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+
+
+
+int prp_create_header(uint32_t xid, Protocol__PrpType type, Protocol__PrpHeader **header) {
+
+ *header = malloc(sizeof(Protocol__PrpHeader));
+ if(*header == NULL)
+ goto error;
+
+ protocol__prp_header__init(*header);
+ (*header)->version = PROGRAN_VERSION;
+ (*header)->has_version = 1;
+ // check if the type is set
+ (*header)->type = type;
+ (*header)->has_type = 1;
+ (*header)->xid = xid;
+ (*header)->has_xid = 1;
+ return 0;
+
+ error:
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int enb_agent_hello(uint32_t xid, Protocol__ProgranMessage **msg) {
+
+ Protocol__PrpHeader *header;
+ if (prp_create_header(xid, PROTOCOL__PRP_TYPE__PRPT_HELLO, &header) != 0)
+ goto error;
+
+ Protocol__PrpHello *hello_msg;
+ hello_msg = malloc(sizeof(Protocol__PrpHello));
+ if(hello_msg == NULL)
+ goto error;
+ protocol__prp_hello__init(hello_msg);
+ hello_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__ProgranMessage));
+ if(*msg == NULL)
+ goto error;
+
+ protocol__progran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__PROGRAN_MESSAGE__MSG_HELLO_MSG;
+ (*msg)->msg_dir = PROTOCOL__PROGRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->hello_msg = hello_msg;
+ return 0;
+
+ error:
+ if(header != NULL)
+ free(header);
+ if(hello_msg != NULL)
+ free(hello_msg);
+ if(*msg != NULL)
+ free(*msg);
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int enb_agent_destroy_hello_message(Protocol__ProgranMessage *msg) {
+
+ if(msg->msg_case != PROTOCOL__PROGRAN_MESSAGE__MSG_HELLO_MSG)
+ goto error;
+
+ free(msg->hello_msg->header);
+ free(msg->hello_msg);
+ free(msg);
+ return 0;
+
+ error:
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int enb_agent_echo_request(uint32_t xid, Protocol__ProgranMessage **msg) {
+ Protocol__PrpHeader *header;
+ if (prp_create_header(xid, PROTOCOL__PRP_TYPE__PRPT_ECHO_REQUEST, &header) != 0)
+ goto error;
+
+ Protocol__PrpEchoRequest *echo_request_msg;
+ echo_request_msg = malloc(sizeof(Protocol__PrpEchoRequest));
+ if(echo_request_msg == NULL)
+ goto error;
+ protocol__prp_echo_request__init(echo_request_msg);
+ echo_request_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__ProgranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__progran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__PROGRAN_MESSAGE__MSG_ECHO_REQUEST_MSG;
+ (*msg)->msg_dir = PROTOCOL__PROGRAN_DIRECTION__INITIATING_MESSAGE;
+ (*msg)->echo_request_msg = echo_request_msg;
+ return 0;
+
+ error:
+ if(header != NULL)
+ free(header);
+ if(echo_request_msg != NULL)
+ free(echo_request_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int enb_agent_destroy_echo_request(Protocol__ProgranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__PROGRAN_MESSAGE__MSG_ECHO_REQUEST_MSG)
+ goto error;
+
+ free(msg->echo_request_msg->header);
+ free(msg->echo_request_msg);
+ free(msg);
+ return 0;
+
+ error:
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+
+int enb_agent_echo_reply(uint32_t xid, Protocol__ProgranMessage **msg) {
+ Protocol__PrpHeader *header;
+ if (prp_create_header(xid, PROTOCOL__PRP_TYPE__PRPT_ECHO_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__PrpEchoReply *echo_reply_msg;
+ echo_reply_msg = malloc(sizeof(Protocol__PrpEchoReply));
+ if(echo_reply_msg == NULL)
+ goto error;
+ protocol__prp_echo_reply__init(echo_reply_msg);
+ echo_reply_msg->header = header;
+
+ *msg = malloc(sizeof(Protocol__ProgranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__progran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__PROGRAN_MESSAGE__MSG_ECHO_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__PROGRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->echo_reply_msg = echo_reply_msg;
+ return 0;
+
+ error:
+ if(header != NULL)
+ free(header);
+ if(echo_reply_msg != NULL)
+ free(echo_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+
+int enb_agent_destroy_echo_reply(Protocol__ProgranMessage *msg) {
+ if(msg->msg_case != PROTOCOL__PROGRAN_MESSAGE__MSG_ECHO_REPLY_MSG)
+ goto error;
+
+ free(msg->echo_reply_msg->header);
+ free(msg->echo_reply_msg);
+ free(msg);
+ return 0;
+
+ error:
+ LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
diff --git a/openair2/ENB_APP/enb_agent_common.h b/openair2/ENB_APP/enb_agent_common.h
new file mode 100644
index 0000000000..3fb0d366ac
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent_common.h
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+
+
+#ifndef ENB_AGENT_COMMON_H_
+#define ENB_AGENT_COMMON_H_
+
+
+#include "header.pb-c.h"
+#include "progran.pb-c.h"
+#include "stats_messages.pb-c.h"
+#include "stats_common.pb-c.h"
+
+#define PROGRAN_VERSION 0
+
+typedef int (*enb_agent_message_decoded_callback)(
+ uint32_t xid,
+ Protocol__ProgranMessage **msg
+);
+
+typedef int32_t err_code_t;
+
+int enb_agent_serialize_message(Protocol__ProgranMessage *msg, void **buf, int *size);
+int enb_agent_deserialize_message(void *data, int size, Protocol__ProgranMessage **msg);
+
+int prp_create_header(uint32_t xid, Protocol__PrpType type, Protocol__PrpHeader **header);
+
+int enb_agent_hello(uint32_t xid, Protocol__ProgranMessage **msg);
+int enb_agent_destroy_hello(Protocol__ProgranMessage *msg);
+
+int enb_agent_echo_request(uint32_t xid, Protocol__ProgranMessage **msg);
+int enb_agent_destroy_echo_request(Protocol__ProgranMessage *msg);
+
+int enb_agent_echo_reply(uint32_t xid, Protocol__ProgranMessage **msg);
+int enb_agent_destroy_echo_reply(Protocol__ProgranMessage *msg);
+
+
+Protocol__ProgranMessage* enb_agent_handle_message (uint32_t xid,
+ uint8_t *data,
+ uint32_t size);
+
+void * enb_agent_send_message(uint32_t xid,
+ Protocol__ProgranMessage *msg,
+ uint32_t * size);
+
+
+#endif
+
+
+
+
+
+
+
diff --git a/openair2/ENB_APP/enb_agent_handler.c b/openair2/ENB_APP/enb_agent_handler.c
new file mode 100644
index 0000000000..2b9509f48e
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent_handler.c
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+
+#include "enb_agent_common.h"
+#include "enb_agent_mac.h"
+#include "log.h"
+
+#include "assertions.h"
+
+enb_agent_message_decoded_callback messages_callback[][3] = {
+ {enb_agent_hello, enb_agent_hello,0}, /*PROTOCOL__PROGRAN_MESSAGE__MSG_HELLO_MSG*/
+ {enb_agent_echo_request, enb_agent_echo_reply,0}, /**/
+ {0, enb_agent_mac_reply,0}, /*stats*/
+ {0,0,0},
+
+};
+
+static const char *enb_agent_direction2String[] = {
+ "", /* not_set */
+ "originating message", /* originating message */
+ "successfull outcome", /* successfull outcome */
+ "unsuccessfull outcome", /* unsuccessfull outcome */
+};
+
+
+Protocol__ProgranMessage* enb_agent_handle_message (uint32_t xid,
+ uint8_t *data,
+ uint32_t size){
+
+ Protocol__ProgranMessage *message;
+ err_code_t err_code;
+ DevAssert(data != NULL);
+
+ if (enb_agent_deserialize_message(data, size, &message) < 0) {
+ err_code= PROTOCOL__PROGRAN_ERR__MSG_DECODING;
+ goto error;
+ }
+
+ if ((message->msg_case > sizeof(messages_callback) / (3*sizeof(enb_agent_message_decoded_callback))) ||
+ (message->msg_dir > PROTOCOL__PROGRAN_DIRECTION__UNSUCCESSFUL_OUTCOME)){
+ err_code= PROTOCOL__PROGRAN_ERR__MSG_NOT_HANDLED;
+ goto error;
+ }
+
+ if (messages_callback[message->msg_case][message->msg_dir] == NULL) {
+ err_code= PROTOCOL__PROGRAN_ERR__MSG_NOT_SUPPORTED;
+ goto error;
+
+ }
+
+ err_code= ((*messages_callback[message->msg_case-1][message->msg_dir-1])(xid, &message));
+ if ( err_code < 0 ){
+ goto error;
+ }
+
+ return message;
+
+error:
+ LOG_E(ENB_APP,"errno %d occured\n",err_code);
+ return err_code;
+
+}
+
+
+
+void * enb_agent_send_message(uint32_t xid,
+ Protocol__ProgranMessage *msg,
+ uint32_t * size){
+
+ void * buffer;
+ err_code_t err_code = PROTOCOL__PROGRAN_ERR__NO_ERR;
+
+ if (enb_agent_serialize_message(msg, &buffer, size) < 0 ) {
+ err_code = PROTOCOL__PROGRAN_ERR__MSG_ENCODING;
+ goto error;
+ }
+
+ // free the msg --> later keep this in the data struct and just update the values
+ enb_agent_mac_destroy_stats_reply(msg);
+
+ DevAssert(buffer !=NULL);
+
+ LOG_D(ENB_APP,"Serilized the enb mac stats reply (size %d)\n", size);
+
+ return buffer;
+
+error :
+LOG_E(ENB_APP,"errno %d occured\n",err_code);
+return NULL;
+
+}
+
+
+
+
+
+
+
+
diff --git a/openair2/ENB_APP/enb_agent_mac.c b/openair2/ENB_APP/enb_agent_mac.c
new file mode 100644
index 0000000000..0399d53d18
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent_mac.c
@@ -0,0 +1,552 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+#include "enb_agent_mac.h"
+#include "enb_agent_common.h"
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/RLC/rlc.h"
+#include "log.h"
+
+int enb_agent_mac_reply(uint32_t xid, Protocol__ProgranMessage **msg){
+
+ void *buffer;
+ int size;
+ err_code_t err_code;
+ // test code
+
+
+ // Create and serialize a stats reply message. This would be done by one of the agents
+ // Let's assume that we want the power headroom, the pending CEs for UEs 1 & 2 and their
+ // DL CQI reports as well as the noise and interference for cell 1
+ report_config_t report_config;
+
+ // We set the flags indicating what kind of stats we need for each UE. Both UEs will have
+ // the same flags in this example
+ uint32_t ue_flags = 0;
+ // Set the power headroom flag
+ ue_flags |= PROTOCOL__PRP_UE_STATS_TYPE__PRUST_PRH;
+ // Set the pending CEs flag
+ ue_flags |= PROTOCOL__PRP_UE_STATS_TYPE__PRUST_MAC_CE_BS;
+ // Set the DL CQI report flag
+ ue_flags |= PROTOCOL__PRP_UE_STATS_TYPE__PRUST_DL_CQI;
+
+ // We do the same with the Cell flags
+ uint32_t c_flags = 0;
+ // Set the noise and interference flag
+ c_flags |= PROTOCOL__PRP_CELL_STATS_TYPE__PRCST_NOISE_INTERFERENCE;
+
+ // We create the appropriate configurations
+ ue_report_type_t ue_configs[2];
+ cc_report_type_t cell_configs[1];
+
+ // Create the config for UE with RNTI 1
+ ue_report_type_t ue1_config;
+ ue1_config.ue_rnti = 1;
+ ue1_config.ue_report_flags = ue_flags;
+
+ // Do the same for UE with RNTI 2
+ ue_report_type_t ue2_config;
+ ue2_config.ue_rnti = 2;
+ ue2_config.ue_report_flags = ue_flags;
+
+ // Add them to the UE list
+ ue_configs[0] = ue1_config;
+ ue_configs[1] = ue2_config;
+
+ // Do the same for cell with id 1
+ cc_report_type_t c1_config;
+ c1_config.cc_id = 1;
+ c1_config.cc_report_flags = c_flags;
+
+ // Add them to the cell list
+ cell_configs[0] = c1_config;
+
+ //Create the full report configuration
+ report_config.nr_ue = 2;
+ report_config.nr_cc = 1;
+ report_config.ue_report_type = ue_configs;
+ report_config.cc_report_type = cell_configs;
+
+ if (enb_agent_mac_stats_reply(xid, &report_config, msg) < 0 ){
+ err_code = PROTOCOL__PROGRAN_ERR__MSG_BUILD;
+ goto error;
+ }
+
+ return 0;
+
+ error :
+ LOG_E(ENB_APP, "errno %d occured\n", err_code);
+ return err_code;
+}
+
+int enb_agent_mac_stats_reply(uint32_t xid,
+ const report_config_t *report_config,
+ Protocol__ProgranMessage **msg) {
+ Protocol__PrpHeader *header;
+ int i, j, k;
+ int cc_id = 0;
+ int enb_id = 0;
+ eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
+ UE_list_t *eNB_UE_list= &eNB->UE_list;
+
+
+ if (prp_create_header(xid, PROTOCOL__PRP_TYPE__PRPT_STATS_REPLY, &header) != 0)
+ goto error;
+
+ Protocol__PrpStatsReply *stats_reply_msg;
+ stats_reply_msg = malloc(sizeof(Protocol__PrpStatsReply));
+ if (stats_reply_msg == NULL)
+ goto error;
+ protocol__prp_stats_reply__init(stats_reply_msg);
+ stats_reply_msg->header = header;
+
+ stats_reply_msg->n_ue_report = report_config->nr_ue;
+ stats_reply_msg->n_cell_report = report_config->nr_cc;
+
+ Protocol__PrpUeStatsReport **ue_report;
+ Protocol__PrpCellStatsReport **cell_report;
+
+
+ /* Allocate memory for list of UE reports */
+ if (report_config->nr_ue > 0) {
+ ue_report = malloc(sizeof(Protocol__PrpUeStatsReport *) * report_config->nr_ue);
+ if (ue_report == NULL)
+ goto error;
+ for (i = 0; i < report_config->nr_ue; i++) {
+ ue_report[i] = malloc(sizeof(Protocol__PrpUeStatsReport));
+ protocol__prp_ue_stats_report__init(ue_report[i]);
+ ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
+ ue_report[i]->has_rnti = 1;
+ ue_report[i]->flags = report_config->ue_report_type[i].ue_report_flags;
+ ue_report[i]->has_flags = 1;
+ /* Check the types of reports that need to be constructed based on flag values */
+
+ /* Check flag for creation of buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_BSR) {
+ //TODO: Create a report for each LCG (4 elements). See prp_ue_stats_report of
+ // progRAN specifications for more details
+ ue_report[i]->n_bsr = 4;
+ uint32_t *elem;
+ elem = (uint32_t *) malloc(sizeof(uint32_t)*ue_report[i]->n_bsr);
+ if (elem == NULL)
+ goto error;
+ for (j = 0; j++; j < ue_report[i]->n_bsr) {
+ // Set the actual BSR for LCG j of the current UE
+ // NN: we need to know the cc_id here, consider the first one
+ elem[j] = eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].bsr_info[j];
+ }
+ ue_report[i]->bsr = elem;
+ }
+
+ /* Check flag for creation of PRH report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_PRH) {
+ // TODO: Fill in the actual power headroom value for the RNTI
+ ue_report[i]->phr = eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].phr_info;
+ ue_report[i]->has_phr = 1;
+ }
+
+ /* Check flag for creation of RLC buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_RLC_BS) {
+ // TODO: Fill in the actual RLC buffer status reports
+ ue_report[i]->n_rlc_report = 1; // Set this to the number of LCs for this UE
+ Protocol__PrpRlcBsr ** rlc_reports;
+ rlc_reports = malloc(sizeof(Protocol__PrpRlcBsr) * ue_report[i]->n_rlc_report);
+ if (rlc_reports == NULL)
+ goto error;
+
+ // Fill the buffer status report for each logical channel of the UE
+ // NN: see LAYER2/openair2_proc.c for rlc status
+ for (j = 0; j < ue_report[i]->n_rlc_report; j++) {
+ rlc_reports[j] = malloc(sizeof(Protocol__PrpRlcBsr));
+ if (rlc_reports[j] == NULL)
+ goto error;
+ protocol__prp_rlc_bsr__init(rlc_reports[j]);
+ //TODO:Set logical channel id
+ rlc_reports[j]->lc_id = 1;
+ rlc_reports[j]->has_lc_id = 1;
+ //TODO:Set tx queue size in bytes
+ rlc_reports[j]->tx_queue_size = 10;
+ rlc_reports[j]->has_tx_queue_size = 1;
+ //TODO:Set tx queue head of line delay in ms
+ rlc_reports[j]->tx_queue_hol_delay = 100;
+ rlc_reports[j]->has_tx_queue_hol_delay = 1;
+ //TODO:Set retransmission queue size in bytes
+ rlc_reports[j]->retransmission_queue_size = 10;
+ rlc_reports[j]->has_retransmission_queue_size = 1;
+ //TODO:Set retransmission queue head of line delay in ms
+ rlc_reports[j]->retransmission_queue_hol_delay = 100;
+ rlc_reports[j]->has_retransmission_queue_hol_delay = 1;
+ //TODO:Set current size of the pending message in bytes
+ rlc_reports[j]->status_pdu_size = 100;
+ rlc_reports[j]->has_status_pdu_size = 1;
+ }
+ // Add RLC buffer status reports to the full report
+ if (ue_report[i]->n_rlc_report > 0)
+ ue_report[i]->rlc_report = rlc_reports;
+ }
+
+ /* Check flag for creation of MAC CE buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_MAC_CE_BS) {
+ // TODO: Fill in the actual MAC CE buffer status report
+ ue_report[i]->pending_mac_ces = -1; /* Use as bitmap. Set one or more of the
+ PROTOCOL__PRP_CE_TYPE__PRPCET_ values
+ found in stats_common.pb-c.h. See
+ prp_ce_type in progRAN specification */
+ ue_report[i]->has_pending_mac_ces = 1;
+ }
+
+ /* Check flag for creation of DL CQI report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_DL_CQI) {
+ // TODO: Fill in the actual DL CQI report for the UE based on its configuration
+ Protocol__PrpDlCqiReport * dl_report;
+ dl_report = malloc(sizeof(Protocol__PrpDlCqiReport));
+ if (dl_report == NULL)
+ goto error;
+ protocol__prp_dl_cqi_report__init(dl_report);
+ //TODO:Set the SFN and SF of the last report held in the agent.
+ dl_report->sfn_sn = eNB->frame*10 + eNB->subframe;
+ dl_report->has_sfn_sn = 1;
+ //TODO:Set the number of DL CQI reports for this UE. One for each CC
+ dl_report->n_csi_report = 1;
+ //TODO:Create the actual CSI reports.
+ Protocol__PrpDlCsi **csi_reports;
+ csi_reports = malloc(sizeof(Protocol__PrpDlCsi *));
+ if (csi_reports == NULL)
+ goto error;
+ for (j = 0; j < dl_report->n_csi_report; j++) {
+ csi_reports[j] = malloc(sizeof(Protocol__PrpDlCsi));
+ if (csi_reports[j] == NULL)
+ goto error;
+ protocol__prp_dl_csi__init(csi_reports[j]);
+ //TODO: the servCellIndex for this report
+ csi_reports[j]->serv_cell_index = 0;
+ csi_reports[j]->has_serv_cell_index = 1;
+ //TODO: the rank indicator value for this cc
+ csi_reports[j]->ri = 1;
+ csi_reports[j]->has_ri = 1;
+ //TODO: the type of CSI report based on the configuration of the UE
+ //For this example we use type P10, which only needs a wideband value
+ //The full set of types can be found in stats_common.pb-c.h and
+ //in the progRAN specifications
+ csi_reports[j]->type = PROTOCOL__PRP_CSI_TYPE__PRCSIT_P10;
+ csi_reports[j]->has_type = 1;
+ csi_reports[j]->report_case = PROTOCOL__PRP_DL_CSI__REPORT_P10CSI;
+ Protocol__PrpCsiP10 *csi10;
+ csi10 = malloc(sizeof(Protocol__PrpCsiP10));
+ if (csi10 == NULL)
+ goto error;
+ protocol__prp_csi_p10__init(csi10);
+ //TODO: set the wideband value
+ // NN: this is also depends on cc_id
+ csi10->wb_cqi = eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].dl_cqi;
+ csi10->has_wb_cqi = 1;
+ //Add the type of measurements to the csi report in the proper union type
+ csi_reports[j]->p10csi = csi10;
+ }
+ //Add the csi reports to the full DL CQI report
+ dl_report->csi_report = csi_reports;
+ //Add the DL CQI report to the stats report
+ ue_report[i]->dl_cqi_report = dl_report;
+ }
+
+ /* Check flag for creation of paging buffer status report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_PBS) {
+ //TODO: Fill in the actual paging buffer status report. For this field to be valid, the RNTI
+ //set in the report must be a P-RNTI
+ Protocol__PrpPagingBufferReport *paging_report;
+ paging_report = malloc(sizeof(Protocol__PrpPagingBufferReport));
+ if (paging_report == NULL)
+ goto error;
+ protocol__prp_paging_buffer_report__init(paging_report);
+ //Set the number of pending paging messages
+ paging_report->n_paging_info = 1;
+ //Provide a report for each pending paging message
+ Protocol__PrpPagingInfo **p_info;
+ p_info = malloc(sizeof(Protocol__PrpPagingInfo *));
+ if (p_info == NULL)
+ goto error;
+ for (j = 0; j < paging_report->n_paging_info; j++) {
+ p_info[j] = malloc(sizeof(Protocol__PrpPagingInfo));
+ if(p_info[j] == NULL)
+ goto error;
+ protocol__prp_paging_info__init(p_info[j]);
+ //TODO: Set paging index. This index is the same that will be used for the scheduling of the
+ //paging message by the controller
+ p_info[j]->paging_index = 10;
+ p_info[j]->has_paging_index = 1;
+ //TODO:Set the paging message size
+ p_info[j]->paging_message_size = 100;
+ p_info[j]->has_paging_message_size = 1;
+ //TODO: Set the paging subframe
+ p_info[j]->paging_subframe = 10;
+ p_info[j]->has_paging_subframe = 1;
+ //TODO: Set the carrier index for the pending paging message
+ p_info[j]->carrier_index = 0;
+ p_info[j]->has_carrier_index = 1;
+ }
+ //Add all paging info to the paging buffer rerport
+ paging_report->paging_info = p_info;
+ //Add the paging report to the UE report
+ ue_report[i]->pbr = paging_report;
+ }
+
+ /* Check flag for creation of UL CQI report */
+ if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_UL_CQI) {
+ //Fill in the full UL CQI report of the UE
+ Protocol__PrpUlCqiReport *full_ul_report;
+ full_ul_report = malloc(sizeof(Protocol__PrpUlCqiReport));
+ if(full_ul_report == NULL)
+ goto error;
+ protocol__prp_ul_cqi_report__init(full_ul_report);
+ //TODO:Set the SFN and SF of the generated report
+ full_ul_report->sfn_sn = 100;
+ full_ul_report->has_sfn_sn = 1;
+ //TODO:Set the number of UL measurement reports based on the types of measurements
+ //configured for this UE and on the servCellIndex
+ full_ul_report->n_cqi_meas = 1;
+ Protocol__PrpUlCqi **ul_report;
+ ul_report = malloc(sizeof(Protocol__PrpUlCqi *) * full_ul_report->n_cqi_meas);
+ if(ul_report == NULL)
+ goto error;
+ //Fill each UL report of the UE for each of the configured report types
+ for(j = 0; j++; j < full_ul_report->n_cqi_meas) {
+ ul_report[j] = malloc(sizeof(Protocol__PrpUlCqi));
+ if(ul_report[j] == NULL)
+ goto error;
+ protocol__prp_ul_cqi__init(ul_report[j]);
+ //TODO: Set the type of the UL report. As an example set it to SRS UL report
+ // See enum prp_ul_cqi_type in progRAN specification for more details
+ ul_report[j]->type = PROTOCOL__PRP_UL_CQI_TYPE__PRUCT_SRS;
+ ul_report[j]->has_type = 1;
+ //TODO:Set the number of SINR measurements based on the report type
+ //See struct prp_ul_cqi in progRAN specification for more details
+ ul_report[j]->n_sinr = 100;
+ uint32_t *sinr_meas;
+ sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[j]->n_sinr);
+ if (sinr_meas == NULL)
+ goto error;
+ //TODO:Set the SINR measurements for the specified type
+ for (k = 0; k < ul_report[j]->n_sinr; k++) {
+ sinr_meas[k] = 10;
+ }
+ ul_report[j]->sinr = sinr_meas;
+ //TODO: Set the servCellIndex for this report
+ ul_report[j]->serv_cell_index = 0;
+ ul_report[j]->has_serv_cell_index = 1;
+ //Set the list of UL reports of this UE to the full UL report
+ full_ul_report->cqi_meas = ul_report;
+ //Add full UL CQI report to the UE report
+ ue_report[i]->ul_cqi_report = full_ul_report;
+ }
+ }
+ }
+ /* Add list of all UE reports to the message */
+ stats_reply_msg->ue_report = ue_report;
+ }
+
+ /* Allocate memory for list of cell reports */
+ if (report_config->nr_cc > 0) {
+ cell_report = malloc(sizeof(Protocol__PrpCellStatsReport *) * report_config->nr_cc);
+ if (cell_report == NULL)
+ goto error;
+ // Fill in the Cell reports
+ for (i = 0; i < report_config->nr_cc; i++) {
+ cell_report[i] = malloc(sizeof(Protocol__PrpCellStatsReport));
+ if(ue_report[i] == NULL)
+ goto error;
+ protocol__prp_cell_stats_report__init(cell_report[i]);
+ cell_report[i]->carrier_index = report_config->cc_report_type[i].cc_id;
+ cell_report[i]->has_carrier_index = 1;
+ cell_report[i]->flags = report_config->cc_report_type[i].cc_report_flags;
+ cell_report[i]->has_flags = 1;
+
+ /* Check flag for creation of noise and interference report */
+ if(report_config->cc_report_type[i].cc_report_flags & PROTOCOL__PRP_CELL_STATS_TYPE__PRCST_NOISE_INTERFERENCE) {
+ // TODO: Fill in the actual noise and interference report for this cell
+ Protocol__PrpNoiseInterferenceReport *ni_report;
+ ni_report = malloc(sizeof(Protocol__PrpNoiseInterferenceReport));
+ if(ni_report == NULL)
+ goto error;
+ protocol__prp_noise_interference_report__init(ni_report);
+ // Current frame and subframe number
+ ni_report->sfn_sf = 0;
+ ni_report->has_sfn_sf = 1;
+ // Received interference power in dbm
+ ni_report->rip = 0;
+ ni_report->has_rip = 1;
+ // Thermal noise power in dbm
+ ni_report->tnp = 0;
+ ni_report->has_tnp = 1;
+ cell_report[i]->noise_inter_report = ni_report;
+ }
+ }
+ /* Add list of all cell reports to the message */
+ stats_reply_msg->cell_report = cell_report;
+ }
+
+ *msg = malloc(sizeof(Protocol__ProgranMessage));
+ if(*msg == NULL)
+ goto error;
+ protocol__progran_message__init(*msg);
+ (*msg)->msg_case = PROTOCOL__PROGRAN_MESSAGE__MSG_STATS_REPLY_MSG;
+ (*msg)->msg_dir = PROTOCOL__PROGRAN_DIRECTION__SUCCESSFUL_OUTCOME;
+ (*msg)->stats_reply_msg = stats_reply_msg;
+ return 0;
+
+ error:
+ // TODO: Need to make proper error handling
+ if (header != NULL)
+ free(header);
+ if (stats_reply_msg != NULL)
+ free(stats_reply_msg);
+ if(*msg != NULL)
+ free(*msg);
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
+
+int enb_agent_mac_destroy_stats_reply(Protocol__ProgranMessage *msg) {
+ //TODO: Need to deallocate memory for the stats reply message
+ if(msg->msg_case != PROTOCOL__PROGRAN_MESSAGE__MSG_STATS_REPLY_MSG)
+ goto error;
+ free(msg->stats_reply_msg->header);
+ int i, j, k;
+
+ Protocol__PrpStatsReply *reply = msg->stats_reply_msg;
+ Protocol__PrpDlCqiReport *dl_report;
+ Protocol__PrpUlCqiReport *ul_report;
+ Protocol__PrpPagingBufferReport *paging_report;
+
+ // Free the memory for the UE reports
+ for (i = 0; i < reply->n_ue_report; i++) {
+ free(reply->ue_report[i]->bsr);
+ for (j = 0; j < reply->ue_report[i]->n_rlc_report; j++) {
+ free(reply->ue_report[i]->rlc_report[j]);
+ }
+ free(reply->ue_report[i]->rlc_report);
+ // If DL CQI report flag was set
+ if (reply->ue_report[i]->flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_DL_CQI) {
+ dl_report = reply->ue_report[i]->dl_cqi_report;
+ // Delete all CSI reports
+ for (j = 0; j < dl_report->n_csi_report; j++) {
+ //Must free memory based on the type of report
+ switch(dl_report->csi_report[j]->report_case) {
+ case PROTOCOL__PRP_DL_CSI__REPORT_P10CSI:
+ free(dl_report->csi_report[j]->p10csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_P11CSI:
+ free(dl_report->csi_report[j]->p11csi->wb_cqi);
+ free(dl_report->csi_report[j]->p11csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_P20CSI:
+ free(dl_report->csi_report[j]->p20csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_P21CSI:
+ free(dl_report->csi_report[j]->p21csi->wb_cqi);
+ free(dl_report->csi_report[j]->p21csi->sb_cqi);
+ free(dl_report->csi_report[j]->p21csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_A12CSI:
+ free(dl_report->csi_report[j]->a12csi->wb_cqi);
+ free(dl_report->csi_report[j]->a12csi->sb_pmi);
+ free(dl_report->csi_report[j]->a12csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_A22CSI:
+ free(dl_report->csi_report[j]->a22csi->wb_cqi);
+ free(dl_report->csi_report[j]->a22csi->sb_cqi);
+ free(dl_report->csi_report[j]->a22csi->sb_list);
+ free(dl_report->csi_report[j]->a22csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_A20CSI:
+ free(dl_report->csi_report[j]->a20csi->sb_list);
+ free(dl_report->csi_report[j]->a20csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_A30CSI:
+ free(dl_report->csi_report[j]->a30csi->sb_cqi);
+ free(dl_report->csi_report[j]->a30csi);
+ break;
+ case PROTOCOL__PRP_DL_CSI__REPORT_A31CSI:
+ free(dl_report->csi_report[j]->a31csi->wb_cqi);
+ for (k = 0; k < dl_report->csi_report[j]->a31csi->n_sb_cqi; k++) {
+ free(dl_report->csi_report[j]->a31csi->sb_cqi[k]);
+ }
+ free(dl_report->csi_report[j]->a31csi->sb_cqi);
+ break;
+ }
+
+ free(dl_report->csi_report[j]);
+ }
+ free(dl_report->csi_report);
+ free(dl_report);
+ }
+ // If Paging buffer report flag was set
+ if (reply->ue_report[i]->flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_PBS) {
+ paging_report = reply->ue_report[i]->pbr;
+ // Delete all paging buffer reports
+ for (j = 0; j < paging_report->n_paging_info; j++) {
+ free(paging_report->paging_info[j]);
+ }
+ free(paging_report->paging_info);
+ free(paging_report);
+ }
+ // If UL CQI report flag was set
+ if (reply->ue_report[i]->flags & PROTOCOL__PRP_UE_STATS_TYPE__PRUST_UL_CQI) {
+ ul_report = reply->ue_report[i]->ul_cqi_report;
+ for (j = 0; j < ul_report->n_cqi_meas; j++) {
+ free(ul_report->cqi_meas[j]->sinr);
+ free(ul_report->cqi_meas[j]);
+ }
+ free(ul_report->cqi_meas);
+ }
+ free(reply->ue_report[i]);
+ }
+ free(reply->ue_report);
+
+ // Free memory for all Cell reports
+ for (i = 0; i < reply->n_cell_report; i++) {
+ free(reply->cell_report[i]->noise_inter_report);
+ free(reply->cell_report[i]);
+ }
+ free(reply->cell_report);
+
+ free(reply);
+ free(msg);
+ return 0;
+
+ error:
+ //LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
+ return -1;
+}
diff --git a/openair2/ENB_APP/enb_agent_mac.h b/openair2/ENB_APP/enb_agent_mac.h
new file mode 100644
index 0000000000..6d36bbb6a1
--- /dev/null
+++ b/openair2/ENB_APP/enb_agent_mac.h
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ OpenAirInterface
+ Copyright(c) 1999 - 2014 Eurecom
+
+ OpenAirInterface is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+
+ OpenAirInterface is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OpenAirInterface.The full GNU General Public License is
+ included in this distribution in the file called "COPYING". If not,
+ see .
+
+ Contact Information
+ OpenAirInterface Admin: openair_admin@eurecom.fr
+ OpenAirInterface Tech : openair_tech@eurecom.fr
+ OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
+
+ Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
+
+ *******************************************************************************/
+
+/*! \file
+ * \brief
+ * \author
+ * \date 2016
+ * \version 0.1
+ */
+
+#ifndef ENB_AGENT_MAC_H_
+#define ENB_AGENT_MAC_H_
+
+#include "header.pb-c.h"
+#include "progran.pb-c.h"
+#include "stats_messages.pb-c.h"
+#include "stats_common.pb-c.h"
+
+
+/* These types will be used to give
+ instructions for the type of stats reports
+ we need to create */
+typedef struct {
+ uint16_t ue_rnti;
+ uint32_t ue_report_flags; /* Indicates the report elements
+ required for this UE id. See
+ ProgRAN specification 1.2.4.2 */
+} ue_report_type_t;
+
+typedef struct {
+ uint16_t cc_id;
+ uint32_t cc_report_flags; /* Indicates the report elements
+ required for this CC index. See
+ ProgRAN specification 1.2.4.3 */
+} cc_report_type_t;
+
+typedef struct {
+ int nr_ue;
+ ue_report_type_t *ue_report_type;
+ int nr_cc;
+ cc_report_type_t *cc_report_type;
+} report_config_t;
+
+
+int enb_agent_mac_reply(uint32_t xid, Protocol__ProgranMessage **msg);
+
+int enb_agent_mac_stats_reply(uint32_t xid, const report_config_t *report_config, Protocol__ProgranMessage **msg);
+
+int enb_agent_mac_destroy_stats_reply(Protocol__ProgranMessage *msg);
+
+#endif
diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c
index 70fb5ad61f..d63d895711 100644
--- a/openair2/ENB_APP/enb_app.c
+++ b/openair2/ENB_APP/enb_app.c
@@ -57,6 +57,10 @@
# include "gtpv1u_eNB_task.h"
# endif
+#if defined(ENB_AGENT_SB_IF)
+# include "enb_agent.h"
+#endif
+
extern unsigned char NB_eNB_INST;
#endif
@@ -310,6 +314,11 @@ void *eNB_app_task(void *args_p)
configure_rrc(enb_id, enb_properties_p);
}
+#if defined (ENB_AGENT_SB_IF)
+ printf("\n start enb agent\n");
+ enb_agent_start();
+#endif
+
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
registered_enb = 0;
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index c1d4d64ef6..7d31f476ef 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -90,6 +90,11 @@ uint8_t config_smbv = 0;
char smbv_ip[16];
#endif
+#if defined(ENB_AGENT_SB_IF)
+# include "enb_agent.h"
+#endif
+
+
#include "oaisim_functions.h"
#include "oaisim.h"
@@ -1332,6 +1337,10 @@ main (int argc, char **argv)
smbv_write_config_from_frame_parms(smbv_fname, &PHY_vars_eNB_g[0][0]->lte_frame_parms);
#endif
+#if defined (ENB_AGENT_SB_IF)
+ enb_agent_start();
+#endif
+
// add events to future event list: Currently not used
//oai_emulation.info.oeh_enabled = 1;
if (oai_emulation.info.oeh_enabled == 1)