enb_agent.c 8.94 KB
Newer Older
nikaeinn's avatar
nikaeinn committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*******************************************************************************
    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 <http://www.gnu.org/licenses/>.

  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.

 *******************************************************************************/

30
31
32
/*! \file enb_agent.h
 * \brief top level enb agent receive thread and itti task
 * \author Navid Nikaein and Xenofon Foukas
nikaeinn's avatar
nikaeinn committed
33
34
35
36
37
38
39
40
 * \date 2016
 * \version 0.1
 */

#include "enb_agent_common.h"
#include "log.h"
#include "enb_agent.h"

41
42
43
44
45
46
47
#include "assertions.h"


enb_agent_instance_t enb_agent[NUM_MAX_ENB_AGENT];
msg_context_t shared_ctxt[NUM_MAX_ENB_AGENT];
/* this could also go into enb_agent struct*/ 
enb_agent_info_t  enb_agent_info;
nikaeinn's avatar
nikaeinn committed
48

49
50
char in_ip[40];
static uint16_t in_port;
nikaeinn's avatar
nikaeinn committed
51

52
53
//void *send_thread(void *args);
void *receive_thread(void *args);
nikaeinn's avatar
nikaeinn committed
54
pthread_t new_thread(void *(*f)(void *), void *b);
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
err_code_t enb_agent_timeout(void* args);

/* 
 * enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller 
 * and can interact with other itti tasks
*/
void *enb_agent_task(void *args){

  MessageDef                     *msg_p           = NULL;
  const char                     *msg_name        = NULL;
  instance_t                      instance;
  int                             result;


  itti_mark_task_ready(TASK_ENB_AGENT);

  do {
    // Wait for a message
    itti_receive_msg (TASK_ENB_AGENT, &msg_p);
    DevAssert(msg_p != NULL);
    msg_name = ITTI_MSG_NAME (msg_p);
    instance = ITTI_MSG_INSTANCE (msg_p);

    switch (ITTI_MSG_ID(msg_p)) {
    case TERMINATE_MESSAGE:
      itti_exit_task ();
      break;

    case MESSAGE_TEST:
      LOG_I(ENB_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
      break;
    
    case TIMER_HAS_EXPIRED:
      enb_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, &msg_p->ittiMsg.timer_has_expired.arg);
      break;

    default:
      LOG_E(ENB_AGENT, "Received unexpected message %s\n", msg_name);
      break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  } while (1);
nikaeinn's avatar
nikaeinn committed
99

100
101
102
103
  return NULL;
}
/*
void *send_thread(void *args) {
nikaeinn's avatar
nikaeinn committed
104

105
  msg_context_t         *d = args;
nikaeinn's avatar
nikaeinn committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  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;
}
123
124
*/
void *receive_thread(void *args) {
nikaeinn's avatar
nikaeinn committed
125

126
  msg_context_t         *d = args;
nikaeinn's avatar
nikaeinn committed
127
128
129
130
131
132
133
134
135
136
137
138
  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;
    }
139
    LOG_D(ENB_AGENT,"received message with size %d\n", size);
nikaeinn's avatar
nikaeinn committed
140
141
  
    
142
    msg=enb_agent_handle_message(d->mod_id, d->rx_xid, data, size);
nikaeinn's avatar
nikaeinn committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156

    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;
      }
157
      LOG_D(ENB_AGENT,"sent message with size %d\n", size);
nikaeinn's avatar
nikaeinn committed
158
159
160
161
162
163
164
    }
    
  }

  return NULL;

error:
165
  LOG_E(ENB_AGENT,"receive_thread: error %d occured\n",err_code);
nikaeinn's avatar
nikaeinn committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  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;
}

195
int enb_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties){
nikaeinn's avatar
nikaeinn committed
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  // 
  set_enb_vars(mod_id, RAN_LTE_OAI);
  enb_agent[mod_id].mod_id = mod_id;
  enb_agent_info.nb_modules+=1;
  
  /* 
   * check the configuration
   */ 
  if (enb_properties->properties[mod_id]->enb_agent_ipv4_address != NULL) {
    strncpy(in_ip, enb_properties->properties[mod_id]->enb_agent_ipv4_address, sizeof(in_ip) );
    in_ip[sizeof(in_ip) - 1] = 0; // terminate string
  } else {
    strcpy(in_ip, DEFAULT_ENB_AGENT_IPv4_ADDRESS ); 
  }
  
  if (enb_properties->properties[mod_id]->enb_agent_port != 0 ) {
    in_port = enb_properties->properties[mod_id]->enb_agent_port;
  } else {
    in_port = DEFAULT_ENB_AGENT_PORT ;
  }
  LOG_I(ENB_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",  
	enb_agent[mod_id].mod_id,
	in_ip,
	in_port);

  //#define TEST_TIMER 0    
#if !defined TEST_TIMER

  /* 
   * create a socket 
   */ 
  enb_agent[mod_id].link = new_link_client(in_ip, in_port);
  if (enb_agent[mod_id].link == NULL) goto error;
  
  LOG_I(ENB_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",  
	enb_agent[mod_id].mod_id,
	in_ip,
	in_port);
  /* 
   * create a message queue
   */ 
  
  enb_agent[mod_id].send_queue = new_message_queue();
  if (enb_agent[mod_id].send_queue == NULL) goto error;
  enb_agent[mod_id].receive_queue = new_message_queue();
  if (enb_agent[mod_id].receive_queue == NULL) goto error;
  
  /* 
   * create a link manager 
   */ 
  
  enb_agent[mod_id].manager = create_link_manager(enb_agent[mod_id].send_queue, enb_agent[mod_id].receive_queue, enb_agent[mod_id].link);
  if (enb_agent[mod_id].manager == NULL) goto error;
nikaeinn's avatar
nikaeinn committed
250

251
252
253
254
255
  memset(&shared_ctxt, 0, sizeof(msg_context_t));
  
  shared_ctxt[mod_id].mod_id = mod_id;
  shared_ctxt[mod_id].tx_mq =  enb_agent[mod_id].send_queue;
  shared_ctxt[mod_id].rx_mq =  enb_agent[mod_id].receive_queue;
nikaeinn's avatar
nikaeinn committed
256

257
258
259
260
261
  /* 
   * start the enb agent rx thread 
   */ 
  
  new_thread(receive_thread, &shared_ctxt[mod_id]);
nikaeinn's avatar
nikaeinn committed
262

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#endif 
  
  /* 
   * initilize a timer 
   */ 
  
  enb_agent_init_timer();
  
  
  
  /* 
   * start the enb agent task for tx and interaction with the underlying network function
   */ 
  
  if (itti_create_task (TASK_ENB_AGENT, enb_agent_task, NULL) < 0) {
    LOG_E(ENB_AGENT, "Create task for eNB Agent failed\n");
    return -1;
  }
nikaeinn's avatar
nikaeinn committed
281
282


283
284
285
286
287
288
289
290
291
292
293
#ifdef TEST_TIMER
  long timer_id=0;
  enb_agent_timer_args_t timer_args;
  memset (&timer_args, 0, sizeof(enb_agent_timer_args_t));
  timer_args.mod_id = mod_id;
  timer_args.cc_actions= ENB_AGENT_ACTION_APPLY;
  timer_args.cc_report_flags = PROTOCOL__PRP_CELL_STATS_TYPE__PRCST_NOISE_INTERFERENCE;
  timer_args.ue_actions =  ENB_AGENT_ACTION_SEND;
  timer_args.ue_report_flags = PROTOCOL__PRP_UE_STATS_TYPE__PRUST_BSR | PROTOCOL__PRP_UE_STATS_TYPE__PRUST_DL_CQI;
  enb_agent_create_timer(1, 0, ENB_AGENT_DEFAULT, mod_id, ENB_AGENT_TIMER_TYPE_PERIODIC, enb_agent_timeout,(void*)&timer_args, &timer_id);
#endif 
nikaeinn's avatar
nikaeinn committed
294
295
296

  //  new_thread(send_thread, &shared_ctxt);

297
  //while (1) pause();
nikaeinn's avatar
nikaeinn committed
298

299
  LOG_I(ENB_AGENT,"client ends\n");
nikaeinn's avatar
nikaeinn committed
300
301
302
  return 0;

error:
303
  LOG_I(ENB_AGENT,"there was an error\n");
nikaeinn's avatar
nikaeinn committed
304
305
306
307
308
309
  return 1;

}



310
311
312
int enb_agent_stop(mid_t mod_id){
  
  int i=0;
nikaeinn's avatar
nikaeinn committed
313

314
315
316
317
318
319
320
321
322
323
324
  enb_agent_destroy_timers();
  for ( i =0; i < enb_agent_info.nb_modules; i++) {
  
    destroy_link_manager(enb_agent[i].manager);
  
    destroy_message_queue(enb_agent[i].send_queue);
    destroy_message_queue(enb_agent[i].receive_queue);
  
    close_link(enb_agent[i].link);
  }
}
nikaeinn's avatar
nikaeinn committed
325

326
327
328
329
330
331
332
333
334
335
336


err_code_t enb_agent_timeout(void* args){

  enb_agent_timer_args_t *timer_args = (enb_agent_timer_args_t *) args;

  LOG_I(ENB_AGENT, "enb_agent %d timeout\n", timer_args->mod_id);
  LOG_I(ENB_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags);
  LOG_I(ENB_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags);
  
  return 0;
nikaeinn's avatar
nikaeinn committed
337
}