dpm-mgmt_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dpm-mgmt_config.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 
00021 #include <sync/common.h>
00022 #include <fnmatch.h>
00023 #include <ddl/dax.h>
00024 #include "dpm-mgmt_config.h"
00025 #include "dpm-mgmt_conn.h"
00026 #include "dpm-mgmt_logging.h"
00027 
00028 #include DPM_OUT_H
00029 
00030 /*** Constants ***/
00031 
00032 
00033 /*** Data Structures ***/
00034 
00038 const char * dpm_config[] = {DDLNAME_SYNC, DDLNAME_SYNC_DPM, NULL};
00039 
00040 /* Configuration DS: */
00041 static boolean     classic_filters;       
00042 static patroot     pol_conf;              
00043 static patroot     sub_conf;              
00044 static TAILQ_HEAD(, int_def_s) int_conf;  
00045 class_list_t logged_in;                   
00046 
00047 
00048 /*** STATIC/INTERNAL Functions ***/
00049 
00054 PATNODE_TO_STRUCT(pol_entry, policer_t, node)
00055 
00056 
00061 PATNODE_TO_STRUCT(sub_entry, subscriber_t, node)
00062 
00063 
00082 static int 
00083 parse_class(dax_walk_data_t * dwd __unused,
00084                   ddl_handle_t * dop,
00085                   int action __unused,
00086                   void * data)
00087 {
00088     subscriber_t * sub = NULL;
00089     ddl_handle_t * conf_op = NULL, * sub_op = NULL;
00090     int rc = DAX_WALK_ABORT;
00091     int check = *((int *)data);
00092     char class_name[MAX_CLASS_NAME + 1];
00093     char pol_name[MAX_POL_NAME + 1];
00094 
00095     junos_trace(DPM_TRACEFLAG_CONF, "%s", __func__);
00096     
00097     INSIST_ERR(dop != NULL);
00098     
00099     if (!dax_get_stringr_by_name(dop, DDLNAME_CLASS_CLASS_NAME,
00100             class_name, sizeof(class_name))) {
00101         dax_error(dop, "Failed to parse class name");
00102         goto failed;
00103     }
00104     
00105     if (!dax_get_stringr_by_name(dop, DDLNAME_CLASS_POLICER,
00106             pol_name, sizeof(pol_name))) {
00107         dax_error(dop, "Failed to parse class policer");
00108         goto failed;
00109     }
00110     
00111     // go thru all subscribers in the class...
00112     
00113     if(!dax_get_object_by_name(dop, DDLNAME_SUBSCRIBER, &conf_op, FALSE)) {
00114         dax_error(dop, "Failed to find any subscribers in the class");
00115         goto failed;
00116     }
00117     
00118     while (dax_visit_container(conf_op, &sub_op)) {
00119         
00120         sub = calloc(1, sizeof(subscriber_t));
00121         INSIST_ERR(sub != NULL);
00122         
00123         if (!dax_get_stringr_by_name(sub_op, DDLNAME_SUBSCRIBER_SUBSCRIBER_NAME,
00124                 sub->subscriber.name, sizeof(sub->subscriber.name))) {
00125             dax_error(sub_op, "Failed to parse subscriber name");
00126             goto failed;
00127         }
00128         
00129         if (!dax_get_stringr_by_name(sub_op, DDLNAME_SUBSCRIBER_PASSWORD,
00130                 sub->subscriber.password, sizeof(sub->subscriber.password))) {
00131             dax_error(sub_op, "Failed to parse subscriber password");
00132             goto failed;
00133         }
00134         
00135         if(check) {
00136             free(sub);
00137             sub = NULL;
00138         } else {
00139             // add it to the configuration
00140             
00141             strcpy(sub->subscriber.class, class_name);
00142             strcpy(sub->subscriber.policer, pol_name);
00143             
00144             patricia_node_init_length(&sub->node,
00145                     strlen(sub->subscriber.name) + 1);
00146 
00147             if(!patricia_add(&sub_conf, &sub->node)) {
00148                 LOG(TRACE_LOG_ERR, "%s: Failed to add "
00149                         "subscriber to configuration", __func__);
00150                 goto failed;
00151             }
00152         }
00153     }
00154     
00155     rc = DAX_WALK_OK;
00156     
00157 failed:
00158     if(conf_op)
00159         dax_release_object(&conf_op);
00160     
00161     if(sub_op)
00162         dax_release_object(&sub_op);
00163 
00164     if(rc != DAX_WALK_OK && sub != NULL)
00165         free(sub);
00166     
00167     return rc;
00168 }
00169 
00170 
00189 static int 
00190 parse_int_default(dax_walk_data_t * dwd __unused,
00191                   ddl_handle_t * dop,
00192                   int action __unused,
00193                   void * data)
00194 {
00195     int_def_t * id = NULL;
00196     int rc = DAX_WALK_ABORT;
00197     int check = *((int *)data);
00198 
00199     junos_trace(DPM_TRACEFLAG_CONF, "%s", __func__);
00200     
00201     INSIST_ERR(dop != NULL);
00202     
00203     id = calloc(1, sizeof(int_def_t));
00204     INSIST_ERR(id != NULL);
00205     
00206     if (!dax_get_stringr_by_name(dop, DDLNAME_IFL_PATTERN_INTERFACE_PATTERN,
00207             id->name_pattern, sizeof(id->name_pattern))) {
00208         dax_error(dop, "Failed to interface default name pattern");
00209         goto failed;
00210     }
00211     
00212     if (!dax_get_stringr_by_name(dop, DDLNAME_IFL_PATTERN_INPUT_POLICER,
00213             id->input_pol, sizeof(id->input_pol))) {
00214         dax_error(dop, "Failed to interface default input policer");
00215         goto failed;
00216     }
00217     
00218     if (!dax_get_stringr_by_name(dop, DDLNAME_IFL_PATTERN_OUTPUT_POLICER,
00219             id->output_pol, sizeof(id->output_pol))) {
00220         dax_error(dop, "Failed to interface default output policer");
00221         goto failed;
00222     }
00223     
00224     if(check) {
00225         free(id);
00226     } else {
00227         // add it to the configuration
00228         TAILQ_INSERT_TAIL(&int_conf, id, entries);
00229     }
00230 
00231     rc = DAX_WALK_OK;
00232     
00233 failed:
00234 
00235     if(rc != DAX_WALK_OK && id != NULL)
00236         free(id);
00237     
00238     return rc;
00239 }
00240 
00241 
00260 static int 
00261 parse_policer(dax_walk_data_t * dwd __unused,
00262               ddl_handle_t * dop,
00263               int action __unused,
00264               void * data)
00265 {
00266     policer_t * pol = NULL;
00267     ddl_handle_t * conf_op = NULL;
00268     int rc = DAX_WALK_ABORT;
00269     char value;
00270     int check = *((int *)data);
00271 
00272     junos_trace(DPM_TRACEFLAG_CONF, "%s", __func__);
00273     
00274     INSIST_ERR(dop != NULL);
00275     
00276     pol = calloc(1, sizeof(policer_t));
00277     INSIST_ERR(pol != NULL);
00278     
00279     if (!dax_get_stringr_by_name(dop, DDLNAME_POL_POLICER_NAME,
00280             pol->policer.name, sizeof(pol->policer.name))) {
00281         dax_error(dop, "Failed to parse policer name");
00282         goto failed;
00283     }
00284     
00285     if(dax_get_object_by_name(dop, DDLNAME_POL_IF_EXCEEDING, &conf_op, FALSE)) {
00286         
00287         if(!dax_get_uint64_by_name(conf_op,
00288                 DDLNAME_POL_IF_EXCEEDING_BURST_SIZE_LIMIT,
00289                 &pol->policer.if_exceeding.burst_size_limit)) {
00290             dax_error(dop, "Failed to parse burst size limit");
00291             goto failed;
00292         }
00293         
00294         if(dax_get_uint_by_name(conf_op,
00295                 DDLNAME_POL_IF_EXCEEDING_BANDWIDTH_PERCENT,
00296                 &pol->policer.if_exceeding.bw_u.bandwidth_percent)) {
00297 
00298             pol->policer.if_exceeding.bw_in_percent = 1;   
00299         } else {
00300             dax_get_uint64_by_name(conf_op,
00301                     DDLNAME_POL_IF_EXCEEDING_BANDWIDTH_LIMIT,
00302                     &pol->policer.if_exceeding.bw_u.bandwidth_limit);
00303         }
00304                 
00305         if(pol->policer.if_exceeding.bw_u.bandwidth_percent == 0 && 
00306                 pol->policer.if_exceeding.bw_u.bandwidth_limit == 0) {
00307             dax_error(dop, "Failed to parse either a bandwidth limit "
00308                     "or a bandwidth percent");
00309             goto failed;
00310         }
00311         
00312         dax_release_object(&conf_op);
00313     }
00314     
00315     if(dax_get_object_by_name(dop, DDLNAME_POL_THEN, &conf_op, FALSE)) {
00316 
00317         if(dax_get_toggle_by_name(conf_op, DDLNAME_POL_THEN_DISCARD,
00318                 &value)) {
00319             pol->policer.action.discard = 1;
00320         }
00321         
00322         dax_get_ubyte_by_name(conf_op, DDLNAME_POL_THEN_LOSS_PRIORITY,
00323                 &pol->policer.action.loss_priority);
00324                 
00325         dax_get_ubyte_by_name(conf_op, DDLNAME_POL_THEN_FORWARDING_CLASS,
00326                 &pol->policer.action.forwarding_class);
00327                 
00328         if(pol->policer.action.discard == 0 && 
00329                 pol->policer.action.loss_priority == 0 && 
00330                 pol->policer.action.forwarding_class == 0) {
00331             dax_error(dop, "Failed to parse an action in the 'then' stanza");
00332             goto failed;
00333         }
00334     }
00335     
00336     if(check) {
00337         free(pol);
00338     } else {
00339         // add it to the configuration
00340         
00341         patricia_node_init_length(&pol->node, strlen(pol->policer.name) + 1);
00342 
00343         if(!patricia_add(&pol_conf, &pol->node)) {
00344             LOG(TRACE_LOG_ERR, "%s: Failed to add "
00345                     "policer to configuration", __func__);
00346             goto failed;
00347         }
00348     }
00349 
00350     rc = DAX_WALK_OK;
00351     
00352 failed:
00353 
00354     if(conf_op)
00355         dax_release_object(&conf_op);
00356 
00357     if(rc != DAX_WALK_OK && pol != NULL)
00358         free(pol);
00359     
00360     return rc;
00361 }
00362 
00363 
00376 static int
00377 match_ifl(kcom_ifl_t * ifl, void * cookie __unused)
00378 {
00379     int_def_t * id;
00380     char full_iflname[MAX_INT_NAME + 1]; 
00381 
00382     sprintf(full_iflname, "%s.%d", ifl->ifl_name, ifl->ifl_subunit);
00383 
00384     // search for a match in all the interface name patterns
00385     id = TAILQ_FIRST(&int_conf);
00386     while(id) {
00387         
00388         if(fnmatch(id->name_pattern, full_iflname, 0) == 0) {
00389             // Send the default policy for this interface
00390             notify_interface_add(ifl->ifl_name, ifl->ifl_subunit, 
00391                     id, ifl->ifl_index);
00392             return KCOM_OK;
00393         }
00394         
00395         id = TAILQ_NEXT(id, entries);
00396     }
00397     
00398     return KCOM_OK;
00399 }
00400 
00401 
00402 /*** GLOBAL/EXTERNAL Functions ***/
00403 
00404 
00408 void
00409 init_config(void)
00410 {
00411     classic_filters = FALSE;
00412     
00413     patricia_root_init(&pol_conf, FALSE, MAX_POL_NAME + 1, 0);
00414     patricia_root_init(&sub_conf, FALSE, MAX_SUB_NAME + 1, 0);
00415     TAILQ_INIT(&int_conf);
00416     TAILQ_INIT(&logged_in);
00417 }
00418 
00419 
00423 void
00424 clear_config(void)
00425 {
00426     policer_t * pol;
00427     int_def_t * id;
00428     subscriber_t * sub;
00429     
00430     junos_trace(DPM_TRACEFLAG_CONF, "%s", __func__);
00431     
00432     classic_filters = FALSE;
00433     
00434     while(NULL != (pol = pol_entry(patricia_find_next(&pol_conf, NULL)))) {
00435 
00436         if(!patricia_delete(&pol_conf, &pol->node)) {
00437             LOG(TRACE_LOG_ERR, "%s: Deleting policer failed", __func__);
00438             continue;
00439         }
00440         free(pol);
00441     }
00442     
00443     while((id = TAILQ_FIRST(&int_conf)) != NULL) {
00444         TAILQ_REMOVE(&int_conf, id, entries);
00445         free(id);
00446     }
00447     
00448     while(NULL != (sub = sub_entry(patricia_find_next(&sub_conf, NULL)))) {
00449 
00450         if(!patricia_delete(&sub_conf, &sub->node)) {
00451             LOG(TRACE_LOG_ERR, "%s: Deleting subscriber failed", __func__);
00452             continue;
00453         }
00454         free(sub);
00455     }
00456     
00457     clear_logins();
00458 }
00459 
00460 
00464 void
00465 clear_logins(void)
00466 {
00467     login_class_t * lc;
00468     login_sub_t * ls;
00469     
00470     while((lc = TAILQ_FIRST(&logged_in)) != NULL) {
00471         
00472         TAILQ_REMOVE(&logged_in, lc, entries);
00473         
00474         while((ls = TAILQ_FIRST(&lc->subs)) != NULL) {
00475             TAILQ_REMOVE(&lc->subs, ls, entries);
00476             free(ls);
00477         }
00478         free(lc);
00479     }
00480 }
00481 
00482 
00486 void
00487 send_configuration(void)
00488 {
00489     policer_t * pol;
00490     subscriber_t * sub;
00491     
00492     junos_trace(DPM_TRACEFLAG_CONF, "%s", __func__);
00493     
00494     notify_configuration_reset(classic_filters);
00495     
00496     pol = pol_entry(patricia_find_next(&pol_conf, NULL));
00497     while(pol != NULL) {
00498         notify_policy_add(&pol->policer);
00499         pol = pol_entry(patricia_find_next(&pol_conf, &pol->node));
00500     }
00501     
00502     if(junos_kcom_ifl_get_all(match_ifl, NULL, NULL) != KCOM_OK) {
00503         LOG(TRACE_LOG_ERR, "%s: Failed to go through IFLs", __func__);
00504     }
00505     
00506     sub = sub_entry(patricia_find_next(&sub_conf, NULL));
00507     while(sub != NULL) {
00508         notify_subscriber_add(&sub->subscriber);
00509         sub = sub_entry(patricia_find_next(&sub_conf, &sub->node));
00510     }
00511     
00512     notify_configuration_complete();
00513 }
00514 
00515 
00525 void
00526 subscriber_login(char * s_name, char * c_name)
00527 {
00528     login_class_t * lc;
00529     login_sub_t * ls;
00530 
00531     // find the class first
00532     lc = TAILQ_FIRST(&logged_in);
00533     while(lc != NULL) {
00534         if(strcmp(lc->class, c_name) == 0) { // found the same class
00535             // insert subscriber
00536             ls = calloc(1, sizeof(login_sub_t));
00537             INSIST_ERR(ls != NULL);
00538             strcpy(ls->name, s_name);
00539             TAILQ_INSERT_TAIL(&lc->subs, ls, entries);
00540             return;
00541         }
00542         
00543         lc = TAILQ_NEXT(lc, entries);
00544     }
00545     
00546     // didn't find a matching class, so create it
00547     lc = calloc(1, sizeof(login_class_t));
00548     INSIST_ERR(lc != NULL);
00549     
00550     ls = calloc(1, sizeof(login_sub_t));
00551     INSIST_ERR(ls != NULL);
00552     
00553     TAILQ_INIT(&lc->subs);
00554     strcpy(lc->class, c_name);
00555     strcpy(ls->name, s_name);
00556     
00557     TAILQ_INSERT_TAIL(&logged_in, lc, entries);
00558     TAILQ_INSERT_TAIL(&lc->subs, ls, entries);
00559 }
00560 
00561 
00571 void
00572 subscriber_logout(char * s_name, char * c_name)
00573 {
00574     login_class_t * lc;
00575     login_sub_t * ls;
00576 
00577     // find the class first
00578     lc = TAILQ_FIRST(&logged_in);
00579     while(lc != NULL) {
00580         if(strcmp(lc->class, c_name) == 0) { // found the same class
00581 
00582             // find the subscriber to remove
00583             ls = TAILQ_FIRST(&lc->subs);
00584             while(ls != NULL) {
00585                 if(strcmp(ls->name, s_name) == 0) { // found the same subscriber
00586                     TAILQ_REMOVE(&lc->subs, ls, entries);
00587                     free(ls);
00588                     // we don't bother cleaning up lc even if lc->subs is empty
00589                     return;
00590                 }
00591                 ls = TAILQ_NEXT(ls, entries);                
00592             }
00593             
00594             junos_trace(DPM_TRACEFLAG_CONF, "%s: (Warning) Didn't find a "
00595                     "matching subscriber", __func__);
00596             return;
00597         }
00598         
00599         lc = TAILQ_NEXT(lc, entries);
00600     }
00601     
00602     junos_trace(DPM_TRACEFLAG_CONF, "%s: (Warning) Didn't find a "
00603             "matching class", __func__);
00604 }
00605 
00606 
00617 int
00618 dpm_config_read(int check)
00619 {
00620     char value;
00621     ddl_handle_t * top = NULL, * dop = NULL;
00622     ddl_handle_t * pol_dop = NULL, * int_dop = NULL, * sub_dop = NULL;
00623     int rc = EFAIL;
00624 
00625     junos_trace(DPM_TRACEFLAG_CONF, "%s: Starting dpm "
00626             "configuration load", __func__);
00627     
00628     // Load the main configuration ...
00629     
00630     if (!dax_get_object_by_path(NULL, dpm_config, &top, FALSE))  {
00631 
00632         junos_trace(DPM_TRACEFLAG_CONF, 
00633                 "%s: Cleared dpm configuration", __func__);
00634 
00635         if(!check)
00636             clear_config();
00637         return SUCCESS;
00638     }
00639     
00640     if (!dax_is_changed(top)) { // if not changed
00641         junos_trace(DPM_TRACEFLAG_CONF, "%s: No change in DPM"
00642             " configuration", __func__);
00643         dax_release_object(&top);
00644         return SUCCESS;
00645     }
00646     
00647     if(!check)
00648         clear_config(); // clear everything and start fresh
00649     
00650     if(dax_get_toggle_by_name(top, DDLNAME_SYNC_DPM_USE_CLASSIC_FILTERS,
00651             &value)) {
00652         classic_filters = TRUE;
00653     }
00654 
00655     if(dax_get_object_by_name(top, DDLNAME_POLICER, &pol_dop, TRUE)) {
00656         if(dax_walk_list(pol_dop, DAX_WALK_CONFIGURED, parse_policer, &check)
00657                 != DAX_WALK_OK) {
00658 
00659             junos_trace(DPM_TRACEFLAG_CONF, "%s: walk policers "
00660                 "list in DPM configuration failed", __func__);
00661             
00662             goto failed;
00663         }
00664     }
00665 
00666     if(dax_get_object_by_name(top, DDLNAME_INT_DEFAULTS, &int_dop, TRUE) &&
00667         dax_get_object_by_name(int_dop, DDLNAME_IFL_PATTERN, &dop, TRUE)) {
00668         
00669         if(dax_walk_list(dop, DAX_WALK_CONFIGURED, parse_int_default, &check)
00670                 != DAX_WALK_OK) {
00671 
00672             junos_trace(DPM_TRACEFLAG_CONF, "%s: walk interface defaults "
00673                 "list in DPM configuration failed", __func__);
00674             
00675             goto failed;
00676         }
00677         dax_release_object(&dop);
00678     }
00679     
00680     if(dax_get_object_by_name(top, DDLNAME_SUBSCRIBER_DB, &sub_dop, TRUE) &&
00681         dax_get_object_by_name(sub_dop, DDLNAME_CLASS, &dop, TRUE)) {
00682         
00683         if(dax_walk_list(dop, DAX_WALK_CONFIGURED, parse_class, &check)
00684                 != DAX_WALK_OK) {
00685 
00686             junos_trace(DPM_TRACEFLAG_CONF, "%s: walk subscriber classes "
00687                 "list in DPM configuration failed", __func__);
00688             
00689             goto failed;
00690         }
00691     }
00692 
00693     if(!check)
00694         send_configuration();
00695     
00696     junos_trace(DPM_TRACEFLAG_CONF, 
00697             "%s: Loaded dpm configuration", __func__);
00698 
00699     rc = SUCCESS;
00700 
00701 failed:
00702 
00703     if(pol_dop)
00704         dax_release_object(&pol_dop);
00705 
00706     if(sub_dop)
00707         dax_release_object(&sub_dop);
00708     
00709     if(int_dop)
00710         dax_release_object(&int_dop);
00711     
00712     if(dop)
00713         dax_release_object(&dop);
00714     
00715     if(top)
00716         dax_release_object(&top);
00717     
00718     return rc;
00719 }

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:55 2010 for SDK Your Net Corporation Dynamic Policy Manager Example: dpm-mgmt 1.0 by Doxygen 1.5.1