dpm-ctrl_main.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dpm-ctrl_main.c 358766 2010-01-20 16:37:38Z jamesk $
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 
00021 /* The Application and This Daemon's Documentation: */
00022 
00416 #include "dpm-ctrl_main.h"
00417 #include "dpm-ctrl_config.h"
00418 #include "dpm-ctrl_conn.h"
00419 #include "dpm-ctrl_http.h"
00420 #include "dpm-ctrl_dfw.h"
00421 #include <jnx/msvcspmon_lib.h>
00422 
00423 /*** Constants ***/
00424 
00428 #define DNAME_DPM_CTRL    "dpm-ctrl"
00429 
00433 #define RETRY_FDB_ATTACH_INTERVAL 5
00434 
00438 #define WAIT_FOR_DFW_INTERVAL 1
00439 
00440 
00444 #define DPM_CTRL_HB_INTERVAL 3
00445 
00446 
00451 #define DPM_CTRL_SICK_INTERVALS 3
00452 
00453 
00458 #define DPM_CTRL_HM_IDENTIFIER "sync-dpm-ctrl"
00459 
00460 
00461 /*** Data Structures ***/
00462 
00463 msp_fdb_handle_t fdb_handle;    
00464 int http_cpu_num;               
00465 
00466 static evContext ev_ctx;        
00467 static evTimerID retry_timer;   
00468 static evTimerID wait_timer;    
00469 static evTimerID hb_timer;      
00470 static struct msvcspmon_client_info * mci; 
00471 
00472 /*** STATIC/INTERNAL Functions ***/
00473 
00474 
00478 static void 
00479 dpm_quit(int signo __unused)
00480 {
00481     LOG(LOG_INFO, "Shutting down");
00482     
00483     if(fdb_handle) {
00484         shutdown_http_server();
00485         msp_fdb_detach(fdb_handle);
00486     }
00487     
00488     shutdown_dfw();
00489     
00490     close_connections();
00491     
00492     clear_configuration();
00493     
00494     if(mci != NULL) {
00495         msvcspmon_unregister(mci);
00496     }
00497 
00498     msp_exit();
00499     
00500     LOG(LOG_INFO, "Shutting down finished");
00501     
00502     exit(0);
00503 }
00504 
00505 
00522 static void
00523 retry_attach_fdb(evContext ctx,
00524                  void * uap __unused,
00525                  struct timespec due __unused,
00526                  struct timespec inter __unused)
00527 {
00528     int rc;
00529     
00530     rc = msp_fdb_attach(NULL, &fdb_handle);
00531     
00532     if(rc == MSP_EAGAIN) {
00533         return; // will retry again later
00534     } else if(rc != MSP_OK) {
00535         LOG(LOG_EMERG, "%s: Failed to attach to the forwarding database. Check "
00536                 "that it is configured (Error code: %d)", __func__, rc);
00537     } else { // it succeeded
00538         evClearTimer(ctx, retry_timer);
00539         evInitID(&retry_timer);
00540         LOG(LOG_INFO, "%s: Attached to FDB", __func__);
00541         
00542         if(!evTestID(wait_timer)) {
00543             // We need FDB attachment and DFW before we can process logins
00544             init_http_server();
00545         }
00546     }
00547 }
00548 
00549 
00566 static void
00567 wait_for_dfw(evContext ctx,
00568              void * uap __unused,
00569              struct timespec due __unused,
00570              struct timespec inter __unused)
00571 {
00572     if(dfw_ready()) {
00573         evClearTimer(ctx, wait_timer);
00574         evInitID(&wait_timer);
00575         LOG(LOG_INFO, "%s: DFW module is ready", __func__);
00576         
00577         // connect to RE now...
00578         if(init_connections(ctx) != SUCCESS) {
00579             LOG(LOG_ALERT, "%s: Failed to intialize. "
00580                     "See error log for details.", __func__);
00581             dpm_quit(0);
00582         }
00583         
00584         if(!evTestID(retry_timer)) {
00585             // We need FDB attachment also before we can process logins
00586             init_http_server();
00587         }
00588     } else {
00589         return;
00590     }
00591 }
00592 
00593 
00609 static void
00610 send_hb(evContext ctx __unused,
00611         void * uap __unused,
00612         struct timespec due __unused,
00613         struct timespec inter __unused)
00614 {
00615     msvcspmon_heartbeat(mci);
00616 }
00617 
00618 
00622 static void
00623 heartbeat_setup_status(msvcspmon_hb_setup_status_t status)
00624 {
00625     if(status != MSVCSPMON_HB_SETUP_SUCCESS) {
00626         LOG(LOG_ERR, "%s: msvcs-pmon infrastructure could not "
00627                 "setup a heartbeat monitor", __func__);
00628         return;
00629     }
00630     
00631     LOG(LOG_INFO, "%s: msvcs-pmon infrastructure setup "
00632             "a heartbeat monitor for this daemon", __func__);
00633     
00634     // turn it on
00635     msvcspmon_heartbeat(mci);
00636     msvcspmon_heartbeat_state(mci, MSVCSPMON_HEARTBEAT_ON);
00637     
00638     evInitID(&hb_timer);
00639     if(evSetTimer(ev_ctx, send_hb, NULL, evAddTime(evNowTime(), 
00640             evConsTime(DPM_CTRL_HB_INTERVAL, 0)),
00641             evConsTime(DPM_CTRL_HB_INTERVAL, 0), &hb_timer)) {
00642 
00643         LOG(LOG_EMERG, "%s: Failed to initialize a timer to send heartbeats. "
00644                 "(Error: %m)", __func__);
00645     }
00646 }
00647 
00648 
00655 static void
00656 hm_connection_status(msvcspmon_connection_status_t status)
00657 {
00658     struct msvcspmon_hb_setup_info mhsi;
00659     
00660     switch(status)
00661     {
00662     case MSVCSPMON_REGISTER_SUCCESS:
00663         LOG(LOG_INFO, "%s: Connection status reported as up", __func__);
00664         
00665         
00666         bzero(&mhsi, sizeof(struct msvcspmon_hb_setup_info));
00667         // mhsi.pid will be setup by API
00668         mhsi.keepalive_interval = DPM_CTRL_HB_INTERVAL * 1000;
00669         mhsi.no_of_missed_keepalive = DPM_CTRL_SICK_INTERVALS;
00670         mhsi.action = MSVCSPMON_ACTION_DEFAULT;
00671         strncpy(mhsi.name, DPM_CTRL_HM_IDENTIFIER, MSVCSPMON_PROC_NAME_LEN);
00672         msvcspmon_setup_heartbeat(mci, &mhsi, heartbeat_setup_status);
00673         
00674         break;
00675         
00676     case MSVCSPMON_CLOSED:
00677         LOG(LOG_INFO, "%s: Connection status reported as closed", __func__);
00678         break;
00679         
00680     case MSVCSPMON_FAILED: 
00681         LOG(LOG_ERR, "%s: Connection status reported as failed", __func__);
00682         break;
00683     
00684     default:
00685         LOG(LOG_ERR, "%s: Connection status reported as unknown", __func__);
00686         break;
00687     }
00688 }
00689 
00690 
00699 static int
00700 dpm_init(evContext ctx)
00701 {
00702     int rc, cpu;
00703 
00704     msp_control_init();
00705     
00706     // Handle some signals that we may receive:
00707     signal(SIGTERM, dpm_quit); // call quit fnc
00708     signal(SIGHUP, SIG_IGN); // ignore
00709     signal(SIGPIPE, SIG_IGN); // ignore
00710     
00711     ev_ctx = ctx;
00712     
00713     // setup some simple health/heartbeat monitoring
00714     mci = msvcspmon_register(ctx, hm_connection_status);
00715     
00716     if(mci == NULL) {
00717         LOG(LOG_ERR, "%s: Registering for health monitoring failed",
00718                 __func__);
00719         goto failed;
00720     }
00721     
00722     // call init function for modules:
00723     
00724     rc = init_configuration();
00725     if(rc != SUCCESS) {
00726         goto failed;
00727     }
00728     
00729     rc = init_dfw(ctx);
00730     if(rc != SUCCESS) {
00731         goto failed;
00732     }
00733     
00734     if(dfw_ready()) {
00735         rc = init_connections(ctx);
00736         if(rc != SUCCESS) {
00737             goto failed;
00738         }
00739     } else {
00740         // need to try again later because FDB isn't initialized yet
00741         evInitID(&wait_timer);
00742         if(evSetTimer(ctx, wait_for_dfw, NULL, evAddTime(evNowTime(), 
00743                 evConsTime(WAIT_FOR_DFW_INTERVAL, 0)),
00744                 evConsTime(WAIT_FOR_DFW_INTERVAL, 0), &wait_timer)) {
00745 
00746             LOG(LOG_EMERG, "%s: Failed to initialize a timer to wait for the "
00747                     "DFW module to become ready (Error: %m)", __func__);
00748             return EFAIL;
00749         }
00750     }
00751     
00752     // find a user CPU number to use for this main thread
00753     cpu = msp_env_get_next_user_cpu(MSP_NEXT_NONE);
00754 
00755     // if at least one valid user cpu available...
00756     if(cpu != MSP_NEXT_END) {
00757 
00758         LOG(LOG_INFO, "%s: Binding main process to user cpu %d",
00759                 __func__, cpu);
00760 
00761         if(msp_process_bind(cpu) != SUCCESS) {
00762             LOG(LOG_ALERT, "%s: Failed to initialize. Cannot bind to user cpu. "
00763                     "See error log for details ", __func__);
00764             dpm_quit(0);
00765             return EFAIL;
00766         }
00767 
00768     } else {
00769         LOG(LOG_EMERG, "%s: Main process will not be bound to a user cpu as "
00770             "expected. System cannot run without a user core.", __func__);
00771     }
00772     
00773     // find another user CPU number to use for the HTTP server
00774     http_cpu_num = msp_env_get_next_user_cpu(cpu);
00775 
00776     if(http_cpu_num == MSP_NEXT_END) {
00777         http_cpu_num = cpu;
00778     }
00779     
00780     LOG(LOG_INFO, "%s: Binding HTTP server thread to user cpu %d",
00781             __func__, http_cpu_num);
00782     
00783     // We are using FDB which is why we need user CPUs
00784     
00785     rc = msp_fdb_attach(NULL, &fdb_handle);
00786     
00787     if(rc == MSP_EAGAIN) {
00788         // need to try again later because FDB isn't initialized yet
00789         evInitID(&retry_timer);
00790         if(evSetTimer(ctx, retry_attach_fdb, NULL, evAddTime(evNowTime(), 
00791                 evConsTime(RETRY_FDB_ATTACH_INTERVAL, 0)),
00792                 evConsTime(RETRY_FDB_ATTACH_INTERVAL, 0), &retry_timer)) {
00793 
00794             LOG(LOG_EMERG, "%s: Failed to initialize a timer to retry "
00795                 "attaching to FDB (Error: %m)", __func__);
00796             return EFAIL;
00797         }
00798     } else if(rc != MSP_OK) {
00799         LOG(LOG_EMERG, "%s: Failed to attach to the forwarding database. Check "
00800                 "that it is configured (Error code: %d)", __func__, rc);
00801         return EFAIL;
00802     } else {
00803         LOG(LOG_INFO, "%s: Attached to FDB", __func__);
00804         
00805         // We need FDB attachment before we can process logins
00806         init_http_server();
00807     }    
00808     
00809     return SUCCESS;
00810     
00811 failed:
00812 
00813     LOG(LOG_ALERT, "%s: Failed to initialize. See error log for details.",
00814             __func__);
00815     dpm_quit(0);
00816     return EFAIL;
00817 }
00818 
00819 
00820 /*** GLOBAL/EXTERNAL Functions ***/
00821 
00822 
00835 int
00836 main(int32_t argc , char **argv)
00837 {
00838     int rc;
00839     mp_sdk_app_ctx_t app_ctx;
00840 
00841     app_ctx = msp_create_app_ctx(argc, argv, DNAME_DPM_CTRL);
00842     msp_set_app_cb_init(app_ctx, dpm_init);
00843 
00844     rc = msp_app_init(app_ctx);
00845 
00846     /* Should never reach this point */
00847     msp_destroy_app_ctx(app_ctx);
00848     return rc;
00849 }
00850 

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