dpm-ctrl_conn.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dpm-ctrl_conn.c 346460 2009-11-14 05:06:47Z ssiano $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  * 
00010  * Copyright (c) 2008, Juniper Networks, Inc.
00011  * All rights reserved.
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 /*** Constants ***/
00029 
00033 #define RETRY_CONNECT 60
00034 #define CONNECT_RETRIES    1  
00035 
00036 
00037 /*** Data Structures ***/
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 /*** STATIC/INTERNAL Functions ***/
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) { // don't bother doing anything yet
00095         return;
00096     }
00097     
00098     INSIST_ERR(pthread_mutex_lock(&msgs_lock) == 0);
00099     
00100     while((msg = TAILQ_FIRST(&notification_msgs)) != NULL) {
00101         
00102         TAILQ_REMOVE(&notification_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             // put message back in and process soon
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(&notification_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         // clear the retry timer
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; // connection will be closed
00197         
00198         // Reconnect to it if timer not going
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; // connection will be closed
00220         
00221         // Reconnect to it if timer not going
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) { // a conf_msg_type_e
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         // change to host byte order
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(&params, sizeof(pconn_client_params_t));
00373     
00374     // setup the client args
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         // Then this is the second time in a row this is called even though it
00382         // didn't fail. We haven't received an event like ESTABLISHED yet.
00383         pconn_client_close(mgmt_client);
00384     }
00385     
00386     // connect
00387     mgmt_client = pconn_client_connect_async(
00388                     &params, 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 /*** GLOBAL/EXTERNAL Functions ***/
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     // Connect to the MGMT component
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(&notification_msgs)) != NULL) {
00448         TAILQ_REMOVE(&notification_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) { // don't bother doing anything yet
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(&notification_msgs, msg, entries);
00491     
00492     INSIST_ERR(pthread_mutex_unlock(&msgs_lock) == 0);
00493     
00494     process_notifications();
00495 }

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:54 2010 for SDK Your Net Corporation Dynamic Policy Manager Example: dpm-ctrl 1.0 by Doxygen 1.5.1