00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00022 #include "dpm-ctrl_main.h"
00023 #include <jnx/pconn.h>
00024 #include "dpm-ctrl_config.h"
00025 #include "dpm-ctrl_conn.h"
00026 #include <sync/dpm_ipc.h>
00027
00028
00029
00033 #define RETRY_CONNECT 60
00034 #define CONNECT_RETRIES 1
00035
00036
00037
00038
00043 typedef struct notification_msg_s {
00044 conf_msg_type_e action;
00045 subscriber_status_t message;
00046 TAILQ_ENTRY(notification_msg_s) entries;
00047 } notification_msg_t;
00048
00049
00053 static TAILQ_HEAD(notification_buffer_s, notification_msg_s) notification_msgs =
00054 TAILQ_HEAD_INITIALIZER(notification_msgs);
00055
00056 static pthread_mutex_t msgs_lock;
00057 static pconn_client_t * mgmt_client;
00058 static evTimerID mgmt_timer_id;
00059 static evContext main_ctx;
00060
00061
00062
00063
00067 static void connect_mgmt(evContext ctx, void * uap,
00068 struct timespec due, struct timespec inter);
00069
00070
00087 static void
00088 process_notifications_messages(evContext ctx UNUSED, void * uap UNUSED,
00089 struct timespec due UNUSED, struct timespec inter UNUSED)
00090 {
00091 notification_msg_t * msg;
00092 int rc = 0;
00093
00094 if(mgmt_client == NULL) {
00095 return;
00096 }
00097
00098 INSIST_ERR(pthread_mutex_lock(&msgs_lock) == 0);
00099
00100 while((msg = TAILQ_FIRST(¬ification_msgs)) != NULL) {
00101
00102 TAILQ_REMOVE(¬ification_msgs, msg, entries);
00103
00104 INSIST_ERR(pthread_mutex_unlock(&msgs_lock) == 0);
00105
00106 rc = pconn_client_send(mgmt_client, msg->action, &msg->message,
00107 sizeof(subscriber_status_t));
00108
00109 if(rc != PCONN_OK) {
00110
00111
00112 LOG(LOG_ERR, "%s: Failed to send message to mgmt component."
00113 " Error: %d", __func__, rc);
00114
00115 INSIST_ERR(pthread_mutex_lock(&msgs_lock) == 0);
00116
00117 TAILQ_INSERT_HEAD(¬ification_msgs, msg, entries);
00118
00119 INSIST_ERR(pthread_mutex_unlock(&msgs_lock) == 0);
00120
00121 if(evSetTimer(main_ctx, process_notifications_messages, NULL,
00122 evAddTime(evNowTime(), evConsTime(5, 0)),
00123 evConsTime(0, 0), NULL)) {
00124
00125 LOG(LOG_EMERG, "%s: evSetTimer() failed! Will not be "
00126 "able to process buffered notifications", __func__);
00127 }
00128 } else {
00129 free(msg);
00130 }
00131
00132 INSIST_ERR(pthread_mutex_lock(&msgs_lock) == 0);
00133 }
00134
00135 INSIST_ERR(pthread_mutex_unlock(&msgs_lock) == 0);
00136 }
00137
00138
00143 static void
00144 process_notifications(void)
00145 {
00146 if(evSetTimer(main_ctx, process_notifications_messages, NULL,
00147 evConsTime(0,0), evConsTime(0, 0), NULL)) {
00148
00149 LOG(LOG_EMERG, "%s: evSetTimer() failed! Will not be "
00150 "able to process buffered notifications", __func__);
00151 }
00152 }
00153
00166 static void
00167 mgmt_client_connection(pconn_client_t * client,
00168 pconn_event_t event,
00169 void * cookie UNUSED)
00170 {
00171 INSIST_ERR(client == mgmt_client);
00172
00173 switch (event) {
00174
00175 case PCONN_EVENT_ESTABLISHED:
00176
00177
00178 if(evTestID(mgmt_timer_id)) {
00179 evClearTimer(main_ctx, mgmt_timer_id);
00180 evInitID(&mgmt_timer_id);
00181 }
00182
00183 LOG(LOG_INFO, "%s: Connected to the dpm-mgmt component "
00184 "on the RE", __func__);
00185
00186 break;
00187
00188 case PCONN_EVENT_SHUTDOWN:
00189
00190 if(mgmt_client != NULL) {
00191 clear_configuration();
00192 LOG(LOG_INFO, "%s: Disconnected from the dpm-mgmt component"
00193 " on the RE", __func__);
00194 }
00195
00196 mgmt_client = NULL;
00197
00198
00199 if(!evTestID(mgmt_timer_id) &&
00200 evSetTimer(main_ctx, connect_mgmt, NULL, evConsTime(0,0),
00201 evConsTime(RETRY_CONNECT, 0), &mgmt_timer_id)) {
00202
00203 LOG(LOG_EMERG, "%s: Failed to initialize a re-connect timer to "
00204 "reconnect to the mgmt component", __func__);
00205 }
00206
00207 break;
00208
00209 case PCONN_EVENT_FAILED:
00210
00211 LOG(LOG_ERR, "%s: Received a PCONN_EVENT_FAILED event", __func__);
00212
00213 if(mgmt_client != NULL) {
00214 clear_configuration();
00215 LOG(LOG_INFO, "%s: Disconnected from the dpm-mgmt component"
00216 " on the RE", __func__);
00217 }
00218
00219 mgmt_client = NULL;
00220
00221
00222 if(!evTestID(mgmt_timer_id) &&
00223 evSetTimer(main_ctx, connect_mgmt, NULL, evConsTime(0,0),
00224 evConsTime(RETRY_CONNECT, 0), &mgmt_timer_id)) {
00225
00226 LOG(LOG_EMERG, "%s: Failed to initialize a re-connect timer to "
00227 "reconnect to the mgmt component", __func__);
00228 }
00229
00230 break;
00231
00232 default:
00233 LOG(LOG_ERR, "%s: Received an unknown pconn event", __func__);
00234 }
00235 }
00236
00237
00253 static status_t
00254 mgmt_client_message(pconn_client_t * session,
00255 ipc_msg_t * msg,
00256 void * cookie UNUSED)
00257 {
00258 INSIST_ERR(session == mgmt_client);
00259 INSIST_ERR(msg != NULL);
00260
00261 switch(msg->subtype) {
00262
00263 case MSG_CONF_RESET:
00264
00265 INSIST_ERR(msg->length == sizeof(reset_info_t));
00266
00267 LOG(LOG_INFO, "%s: Received a configuration update: "
00268 "reset configuration (%d)", __func__,
00269 ((reset_info_t *)msg->data)->use_classic_filters);
00270
00271 reset_configuration(((reset_info_t *)msg->data)->use_classic_filters);
00272
00273 break;
00274
00275 case MSG_CONF_COMP:
00276
00277 INSIST_ERR(msg->length == 0);
00278
00279 LOG(LOG_INFO, "%s: Received a configuration update: "
00280 "configuration complete", __func__);
00281
00282 configuration_complete();
00283
00284 break;
00285
00286 case MSG_POLICER:
00287 {
00288 policer_info_t * data = (policer_info_t *)msg->data;
00289
00290 INSIST_ERR(msg->length == sizeof(policer_info_t));
00291
00292 LOG(LOG_INFO, "%s: Received a configuration update: "
00293 "configure policer %s", __func__, data->name);
00294
00295
00296 data->if_exceeding.burst_size_limit =
00297 ntohq(data->if_exceeding.burst_size_limit);
00298
00299 if(data->if_exceeding.bw_in_percent) {
00300 data->if_exceeding.bw_u.bandwidth_percent =
00301 ntohl(data->if_exceeding.bw_u.bandwidth_percent);
00302 } else {
00303 data->if_exceeding.bw_u.bandwidth_limit =
00304 ntohq(data->if_exceeding.bw_u.bandwidth_limit);
00305 }
00306
00307 configure_policer(data);
00308
00309 break;
00310 }
00311 case MSG_INTERFACE:
00312 {
00313 int_info_t * data = (int_info_t *)msg->data;
00314 INSIST_ERR(msg->length == sizeof(int_info_t));
00315
00316 data->subunit = ntohl(data->subunit);
00317 data->index = ntohl(data->index);
00318
00319 LOG(LOG_INFO, "%s: Received a configuration update: "
00320 "configure managed interface %s.%d", __func__,
00321 data->name, data->subunit);
00322
00323 configure_managed_interface(data);
00324
00325 break;
00326 }
00327 case MSG_SUBSCRIBER:
00328 {
00329 sub_info_t * data = (sub_info_t *)msg->data;
00330 INSIST_ERR(msg->length == sizeof(sub_info_t));
00331
00332 LOG(LOG_INFO, "%s: Received a configuration update: "
00333 "configure subscriber %s", __func__, data->name);
00334
00335 configure_subscriber(data);
00336
00337 break;
00338 }
00339 default:
00340 LOG(LOG_ERR, "%s: Received an unknown message type (%d) from the "
00341 "mgmt component", __func__, msg->subtype);
00342 return EFAIL;
00343 }
00344
00345 return SUCCESS;
00346 }
00347
00348
00364 static void
00365 connect_mgmt(evContext ctx,
00366 void * uap UNUSED,
00367 struct timespec due UNUSED,
00368 struct timespec inter UNUSED)
00369 {
00370 pconn_client_params_t params;
00371
00372 bzero(¶ms, sizeof(pconn_client_params_t));
00373
00374
00375 params.pconn_peer_info.ppi_peer_type = PCONN_PEER_TYPE_RE;
00376 params.pconn_port = DPM_PORT_NUM;
00377 params.pconn_num_retries = CONNECT_RETRIES;
00378 params.pconn_event_handler = mgmt_client_connection;
00379
00380 if(mgmt_client) {
00381
00382
00383 pconn_client_close(mgmt_client);
00384 }
00385
00386
00387 mgmt_client = pconn_client_connect_async(
00388 ¶ms, ctx, mgmt_client_message, NULL);
00389
00390 if(mgmt_client == NULL) {
00391 LOG(LOG_ERR, "%s: Failed to initialize the pconn client connection "
00392 "to the mgmt component", __func__);
00393 }
00394
00395 LOG(LOG_INFO, "%s: Trying to connect to the mgmt component", __func__);
00396 }
00397
00398
00399
00400
00401
00411 status_t
00412 init_connections(evContext ctx)
00413 {
00414 mgmt_client = NULL;
00415 main_ctx = ctx;
00416 evInitID(&mgmt_timer_id);
00417 pthread_mutex_init(&msgs_lock, NULL);
00418
00419
00420 if(evSetTimer(ctx, connect_mgmt, NULL, evNowTime(),
00421 evConsTime(RETRY_CONNECT, 0), &mgmt_timer_id)) {
00422
00423 LOG(LOG_EMERG, "%s: Failed to initialize a connect timer to connect "
00424 "to the MGMT component", __func__);
00425 return EFAIL;
00426 }
00427
00428 return SUCCESS;
00429 }
00430
00431
00435 void
00436 close_connections(void)
00437 {
00438 notification_msg_t * msg;
00439
00440 if(mgmt_client) {
00441 pconn_client_close(mgmt_client);
00442 mgmt_client = NULL;
00443 }
00444
00445 INSIST_ERR(pthread_mutex_lock(&msgs_lock) == 0);
00446
00447 while((msg = TAILQ_FIRST(¬ification_msgs)) != NULL) {
00448 TAILQ_REMOVE(¬ification_msgs, msg, entries);
00449 free(msg);
00450 }
00451
00452 INSIST_ERR(pthread_mutex_unlock(&msgs_lock) == 0);
00453
00454 pthread_mutex_destroy(&msgs_lock);
00455 }
00456
00457
00470 void
00471 notify_status_update(status_msg_type_e action,
00472 char * subscriber_name,
00473 char * class_name)
00474 {
00475 notification_msg_t * msg;
00476
00477 if(mgmt_client == NULL) {
00478 return;
00479 }
00480
00481 msg = calloc(1, sizeof(notification_msg_t));
00482 INSIST_ERR(msg != NULL);
00483
00484 msg->action = action;
00485 strcpy(msg->message.name, subscriber_name);
00486 strcpy(msg->message.class, class_name);
00487
00488 INSIST_ERR(pthread_mutex_lock(&msgs_lock) == 0);
00489
00490 TAILQ_INSERT_TAIL(¬ification_msgs, msg, entries);
00491
00492 INSIST_ERR(pthread_mutex_unlock(&msgs_lock) == 0);
00493
00494 process_notifications();
00495 }