equilibrium2-mgmt_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: equilibrium2-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/equilibrium2.h>
00022 #include "equilibrium2-mgmt.h"
00023 
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <arpa/inet.h>
00027 #include <jnx/trace.h>
00028 #include <jnx/junos_trace.h>
00029 #include <ddl/ddl.h>
00030 #include <ddl/dax.h>
00031 
00032 #include EQUILIBRIUM2_OUT_H
00033 
00034 /*** Constants ***/
00035 
00036 #define DDLNAME_SVC_SET_NAME    "service-set-name"
00037 
00038 #define DDLNAME_EXT_SVC         "extension-service"
00039 
00040 #define DDLNAME_EXT_SVC_NAME    "service-name"
00041 
00042 #define DDLNAME_IF_SVC          "interface-service"
00043 
00044 #define DDLNAME_IF_SVC_IF_NAME  "service-interface"
00045 
00047 /*** Data Structures ***/
00048 
00049 static svc_gate_head_t  svc_gate_head;   
00050 static svc_type_head_t  svc_type_head;   
00051 static svr_group_head_t svr_group_head;  
00052 static int              svr_group_count; 
00053 static svc_set_head_t   ss_head;         
00054 static ssrb_head_t      ssrb_head;       
00055 static blob_ss_head_t   blob_ss_head;    
00056 static svc_rule_head_t       balance_rule_head;
00058 static svc_rule_head_t       classify_rule_head;
00060 static blob_svr_group_set_t  *blob_svr_group_set;
00063 /*** STATIC/INTERNAL Functions ***/
00064 
00069 static void
00070 clear_svc_if (void)
00071 {
00072     svc_if_t *svc_if;
00073 
00074     while ((svc_if = LIST_FIRST(&svc_if_head))) {
00075         LIST_REMOVE(svc_if, entry);
00076         free(svc_if);
00077     }
00078     svc_if_count = 0;
00079 }
00080 
00088 static void
00089 add_svc_if (char *name)
00090 {
00091     svc_if_t *svc_if;
00092 
00093     /* If interface name exists, return. */
00094     LIST_FOREACH(svc_if, &svc_if_head, entry) {
00095         if (strcmp(svc_if->if_name, name) == 0) {
00096             return;
00097         }
00098     }
00099     svc_if = malloc(sizeof(svc_if_t));
00100     INSIST_ERR(svc_if != NULL);
00101     svc_if->if_name = name;
00102     LIST_INSERT_HEAD(&svc_if_head, svc_if, entry);
00103     svc_if_count++;
00104 }
00105 
00119 static svc_rule_t *
00120 get_eq2_svc_rule (svc_rule_head_t *head, char *name)
00121 {
00122     svc_rule_t *rule;
00123 
00124     if ((head == NULL) || (name == NULL)) {
00125         return NULL;
00126     }
00127     LIST_FOREACH(rule, head, entry) {
00128         if (strcmp(rule->rule_name, name) == 0) {
00129             break;
00130         }
00131     }
00132     return rule;
00133 }
00134 
00148 static blob_svc_set_node_t *
00149 get_svc_set_blob_node (char *name, int eq2_svc)
00150 {
00151     blob_svc_set_node_t *blob_ss_node;
00152 
00153     LIST_FOREACH(blob_ss_node, &blob_ss_head, entry) {
00154         if ((strcmp(blob_ss_node->ss->ss_name, name) == 0) &&
00155                 (blob_ss_node->ss->ss_eq2_svc_id == eq2_svc)) {
00156             break;
00157         }
00158     }
00159     return blob_ss_node;
00160 }
00161 
00169 static void
00170 free_eq2_svc_rule (svc_rule_t *rule)
00171 {
00172     svc_term_t *term;
00173 
00174     if (rule == NULL) {
00175         return;
00176     }
00177 
00178     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s %s", __func__, rule->rule_name);  
00179 
00180     /* Clear all terms in this rule. */
00181     while ((term = LIST_FIRST(&rule->rule_term_head))) {
00182         LIST_REMOVE(term, entry);
00183         free(term);
00184     }
00185     free(rule);
00186 }
00187 
00198 static void
00199 del_eq2_svc_rule (svc_rule_t *rule)
00200 {
00201     if (rule == NULL) {
00202         return;
00203     }
00204 
00205     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s %s", __func__, rule->rule_name);
00206 
00207     /* Remove the service rule from the list it belongs to */
00208     LIST_REMOVE(rule, entry);
00209 
00210     /* Free the service rule */
00211     free_eq2_svc_rule(rule);
00212 }
00213 
00221 static void
00222 clear_eq2_svc_rule (svc_rule_head_t *head)
00223 {
00224     svc_rule_t *rule;
00225 
00226     if (head == NULL) {
00227         return;
00228     }
00229     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s", __func__);
00230 
00231     /* Remove each service rule in the list and free it. */
00232     while ((rule = LIST_FIRST(head))) {
00233         LIST_REMOVE(rule, entry);
00234         free_eq2_svc_rule(rule);
00235     }
00236 }
00237 
00245 static void
00246 del_svc_set (svc_set_t *ss)
00247 {
00248     svc_set_rule_t *rule;
00249 
00250     if (ss == NULL) {
00251         return;
00252     }
00253 
00254     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s %s", __func__, ss->ss_name);
00255 
00256     LIST_REMOVE(ss, entry);
00257 
00258     /* Clear all rules in this service set. */
00259     while ((rule = LIST_FIRST(&ss->ss_rule_head))) {
00260         LIST_REMOVE(rule, entry);
00261         free(rule);
00262     }
00263     free(ss);
00264 }
00265 
00270 static void
00271 clear_svc_set (void)
00272 {
00273     svc_set_t *ss;
00274 
00275     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s", __func__);
00276 
00277     while ((ss = LIST_FIRST(&ss_head))) {
00278         del_svc_set(ss);
00279     }
00280 }
00281 
00292 static ssrb_node_t *
00293 config_get_ssrb (char *name)
00294 {
00295     ssrb_node_t *ssrb;
00296 
00297     if (name == NULL) {
00298         return NULL;
00299     }
00300     LIST_FOREACH(ssrb, &ssrb_head, entry) {
00301         if (strcmp(ssrb->ssrb.svc_set_name, name) == 0) {
00302             break;
00303         }
00304     }
00305     return ssrb;
00306 }
00307 
00321 static int
00322 read_svc_set_rule (ddl_handle_t *dop, svc_set_rule_head_t *head)
00323 {
00324     const char *rule_config[] = { "rule", NULL };
00325     ddl_handle_t *dop_rule_head = NULL;
00326     ddl_handle_t *dop_rule = NULL;
00327     char rule_name[MAX_NAME_LEN];
00328     svc_set_rule_t *rule;
00329     int count = 0;
00330 
00331     if (!dax_get_object_by_path(dop, rule_config, &dop_rule_head, FALSE)) {
00332         dax_error(dop, "No rules configured!");
00333         dax_release_object(&dop_rule_head);
00334         return -1;
00335     }
00336     while (dax_visit_container(dop_rule_head, &dop_rule)) {
00337         if (!dax_get_stringr_by_name(dop_rule, "name", rule_name,
00338                 sizeof(rule_name))) {
00339             continue;
00340         }
00341         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Read rule %s.", __func__, rule_name);
00342         rule = malloc(sizeof(svc_set_rule_t));
00343         INSIST_ERR(rule != NULL);
00344         strlcpy(rule->rule_name, rule_name, sizeof(rule->rule_name));
00345         LIST_INSERT_HEAD(head, rule, entry);
00346         count++;
00347     }
00348     dax_release_object(&dop_rule_head);
00349     return count;
00350 }
00351 
00362 static int 
00363 read_svc_set (ddl_handle_t *dop_ss)
00364 {
00365     const char *svc_if_config[] = { DDLNAME_IF_SVC, NULL };
00366     const char *ext_svc_config[] = { DDLNAME_EXT_SVC, NULL };
00367     ddl_handle_t *dop_svc_if = NULL;
00368     ddl_handle_t *dop_ext_svc_head = NULL;
00369     ddl_handle_t *dop_ext_svc = NULL;
00370     char svc_if_name[MAX_NAME_LEN];
00371     char ext_svc_name[MAX_NAME_LEN];
00372     char ss_name[MAX_NAME_LEN];
00373     svc_set_t *ss;
00374     svc_set_rule_head_t balance_rl_head;
00375     svc_set_rule_head_t classify_rl_head;
00376     int balance_rule_count = 0;
00377     int classify_rule_count = 0;
00378     ssrb_node_t *ssrb_node;
00379 
00380     /* Read service-set name. */
00381     if (!dax_get_stringr_by_name(dop_ss, DDLNAME_SVC_SET_NAME, ss_name,
00382             sizeof(ss_name))) {
00383         dax_error(dop_ss, "Parse a service set name ERROR!");
00384         return -1;
00385     }
00386 
00387     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Reading %s.", __func__, ss_name);
00388 
00389     /* Get the head object of extension-service list. */
00390     if (!dax_get_object_by_path(dop_ss, ext_svc_config, &dop_ext_svc_head,
00391             FALSE)) {
00392         /* No external service configured. */
00393         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No external service.", __func__);
00394         return -1;
00395     }
00396 
00397     /* Read interface-service. */
00398     if (!dax_get_object_by_path(dop_ss, svc_if_config, &dop_svc_if, FALSE)) {
00399         dax_error(dop_ss, "Service interface is not configured!");
00400         return -1;
00401     }
00402 
00403     /* Read service-interface. */
00404     if (!dax_get_stringr_by_name(dop_svc_if, DDLNAME_IF_SVC_IF_NAME,
00405             svc_if_name, sizeof(svc_if_name))) {
00406         dax_error(dop_svc_if, "Read service-interface name ERROR!");
00407         dax_release_object(&dop_svc_if);
00408         return -1;
00409     }
00410     dax_release_object(&dop_svc_if);
00411 
00412     LIST_INIT(&balance_rl_head);
00413     balance_rule_count = 0;
00414     LIST_INIT(&classify_rl_head);
00415     classify_rule_count = 0;
00416     while (dax_visit_container(dop_ext_svc_head, &dop_ext_svc)) {
00417         if (!dax_get_stringr_by_name(dop_ext_svc, DDLNAME_EXT_SVC_NAME,
00418                 ext_svc_name, sizeof(ext_svc_name))) {
00419             dax_error(dop_ext_svc, "Read external service name ERROR!");
00420             dax_release_object(&dop_ext_svc);
00421             dax_release_object(&dop_ext_svc_head);
00422             return -1;
00423         }
00424 
00425         if (strcmp(ext_svc_name, EQ2_BALANCE_SVC_NAME) == 0) {
00426             EQ2_TRACE(EQ2_TRACEFLAG_CONF,
00427                         "%s: Equilibrium2 balance service.", __func__);
00428             balance_rule_count = read_svc_set_rule(dop_ext_svc,
00429                         &balance_rl_head);
00430             if (balance_rule_count <= 0) {
00431 
00432                 /* Read rules error or no rules. */
00433                 dax_error(dop_ext_svc, "Read balance rules ERROR!");
00434                 dax_release_object(&dop_ext_svc);
00435                 dax_release_object(&dop_ext_svc_head);
00436                 return -1;
00437             }
00438         }
00439         if (strcmp(ext_svc_name, EQ2_CLASSIFY_SVC_NAME) == 0) {
00440             EQ2_TRACE(EQ2_TRACEFLAG_CONF,
00441                     "%s: Equilibrium2 classify service.", __func__);
00442             classify_rule_count = read_svc_set_rule(dop_ext_svc,
00443                     &classify_rl_head);
00444             if (classify_rule_count <= 0) {
00445 
00446                 /* Read rules error or no rules. */
00447                 dax_error(dop_ext_svc, "Read classify rules ERROR!");
00448                 dax_release_object(&dop_ext_svc);
00449                 dax_release_object(&dop_ext_svc_head);
00450                 return -1;
00451             }
00452         }
00453     }
00454     dax_release_object(&dop_ext_svc_head);
00455 
00456     if (balance_rule_count > 0) {
00457         ss = calloc(1, sizeof(svc_set_t));
00458         INSIST_ERR(ss != NULL);
00459         strlcpy(ss->ss_name, ss_name, sizeof(ss->ss_name));
00460         strlcpy(ss->ss_if_name, svc_if_name, sizeof(ss->ss_if_name));
00461         ss->ss_eq2_svc_id = EQ2_BALANCE_SVC;
00462 
00463         LIST_INSERT_HEAD(&ss->ss_rule_head, LIST_FIRST(&balance_rl_head),
00464             entry);
00465         ss->ss_rule_count = balance_rule_count;
00466         LIST_INSERT_HEAD(&ss_head, ss, entry);
00467         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Read %d balance rules.",
00468                 __func__, balance_rule_count);
00469     }
00470     if (classify_rule_count > 0) {
00471         ss = calloc(1, sizeof(svc_set_t));
00472         INSIST_ERR(ss != NULL);
00473         strlcpy(ss->ss_name, ss_name, sizeof(ss->ss_name));
00474         strlcpy(ss->ss_if_name, svc_if_name, sizeof(ss->ss_if_name));
00475         ss->ss_eq2_svc_id = EQ2_CLASSIFY_SVC;
00476 
00477         LIST_INSERT_HEAD(&ss->ss_rule_head, LIST_FIRST(&classify_rl_head),
00478                 entry);
00479         ss->ss_rule_count = classify_rule_count;
00480         LIST_INSERT_HEAD(&ss_head, ss, entry);
00481         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Read %d classify rules.",
00482                 __func__, classify_rule_count);
00483     }
00484 
00485     /* If this service-set is changed and it contains Equilibrium II service,
00486      * the associated SSRB is expected to be updated as well.
00487      * If the SSRB state is 'updated', meaning SSRB update was received before
00488      * reading config, then do nothing.
00489      * Otherwise, it means SSRB update was not received yet and is expected
00490      * to be received after reading config, then mark the SSRB 'pending'.
00491      */
00492     if (dax_is_changed(dop_ss) && (balance_rule_count > 0 ||
00493             classify_rule_count >0)) {
00494         ssrb_node = config_get_ssrb(ss_name);
00495         if (ssrb_node && (ssrb_node->ssrb_state != SSRB_UPDATED)) {
00496             ssrb_node->ssrb_state = SSRB_PENDING;
00497         }
00498     }
00499 
00500     return 0;
00501 }
00502 
00513 static void
00514 add_eq2_svc_gate (char *name, char *addr)
00515 {
00516     svc_gate_t *gate;
00517 
00518     if ((name == NULL) || (addr == NULL)) {
00519         return;
00520     }
00521     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s %s: %s", __func__, name, addr);
00522 
00523     gate = malloc(sizeof(svc_gate_t));
00524     INSIST_ERR(gate != NULL);
00525 
00526     strlcpy(gate->gate_name, name, sizeof(gate->gate_name));
00527     gate->gate_addr = inet_addr(addr);
00528 
00529     LIST_INSERT_HEAD(&svc_gate_head, gate, entry);
00530 }
00531 
00542 static in_addr_t
00543 get_eq2_svc_gate (char *name)
00544 {
00545     svc_gate_t *gate;
00546 
00547     if (name == NULL) {
00548         return 0;
00549     }
00550     LIST_FOREACH(gate, &svc_gate_head, entry) {
00551         if (strcmp(gate->gate_name, name) == 0) {
00552             break;
00553         }
00554     }
00555     return (gate ? gate->gate_addr : INADDR_ANY);
00556 }
00557 
00568 static void
00569 add_eq2_svc_type (char *name, uint16_t port)
00570 {
00571     svc_type_t *type;
00572 
00573     if ((name == NULL) || (port == 0)) {
00574         return;
00575     }
00576     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s %s: %d", __func__, name, port);
00577 
00578     type = malloc(sizeof(svc_type_t));
00579     INSIST_ERR(type != NULL);
00580 
00581     strlcpy(type->type_name, name, sizeof(type->type_name));
00582     type->type_port = port;
00583 
00584     LIST_INSERT_HEAD(&svc_type_head, type, entry);
00585 }
00586 
00597 static uint16_t
00598 get_eq2_svc_type (char *name)
00599 {
00600     svc_type_t *type;
00601 
00602     if (name == NULL) {
00603         return 0;
00604     }
00605     LIST_FOREACH(type, &svc_type_head, entry) {
00606         if (strcmp(type->type_name, name) == 0) {
00607             break;
00608         }
00609     }
00610     return (type ? type->type_port : 0);
00611 }
00612 
00626 static void
00627 add_eq2_svr_group (char *name, svr_addr_head_t *head, int addr_count)
00628 {
00629     svr_group_t *group;
00630     svr_addr_t *addr;
00631 
00632     if ((name == NULL) || (head == NULL)) {
00633         return;
00634     }
00635     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: %s", __func__, name);
00636 
00637     group = calloc(1, sizeof(svr_group_t));
00638     INSIST_ERR(group != NULL);
00639 
00640     LIST_INIT(&group->group_addr_head);
00641     strlcpy(group->group_name, name, sizeof(group->group_name));
00642 
00643     /* Move addresses from temp list to group address list. */
00644     while ((addr = LIST_FIRST(head))) {
00645         LIST_REMOVE(addr, entry);
00646         LIST_INSERT_HEAD(&group->group_addr_head, addr, entry);
00647     }
00648     group->group_addr_count = addr_count;
00649 
00650     /* Add group to the list. */
00651     LIST_INSERT_HEAD(&svr_group_head, group, entry);
00652     svr_group_count++;
00653 }
00654 
00659 static void
00660 clear_eq2_svc_gate (void)
00661 {
00662     svc_gate_t *gate;
00663 
00664     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s", __func__);
00665 
00666     while ((gate = LIST_FIRST(&svc_gate_head))) {
00667         LIST_REMOVE(gate, entry);
00668         free(gate);
00669     }
00670 }
00671 
00676 static void
00677 clear_eq2_svc_type (void)
00678 {
00679     svc_type_t *type;
00680 
00681     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s", __func__);
00682     while ((type = LIST_FIRST(&svc_type_head)) != NULL) {
00683         LIST_REMOVE(type, entry);
00684         free(type);
00685     }
00686 }
00687 
00692 static void
00693 clear_eq2_svr_group (void)
00694 { 
00695     svr_group_t *group;
00696     svr_addr_t *addr;
00697 
00698     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s", __func__);
00699     while ((group = LIST_FIRST(&svr_group_head))) {
00700         LIST_REMOVE(group, entry);
00701         while ((addr = LIST_FIRST(&group->group_addr_head))) {
00702             LIST_REMOVE(addr, entry);
00703             free(addr);
00704         }
00705         free(group);
00706     } 
00707     svr_group_count = 0;
00708 }
00709 
00714 static void
00715 read_eq2_svc_gate (void)
00716 {
00717     ddl_handle_t *cop = NULL;
00718     ddl_handle_t *dop = NULL;
00719     const char *svc_gate_config[] = { "sync", "equilibrium2", "service-gate",
00720             NULL };
00721     char name_str[MAX_NAME_LEN];
00722     char addr_str[MAX_NAME_LEN];
00723 
00724     if (!dax_get_object_by_path(NULL, svc_gate_config, &cop, FALSE)) {
00725         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No service-gate.", __func__);
00726         clear_eq2_svc_gate();
00727         return;
00728     }
00729     if (!dax_is_changed(cop)) {
00730         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No change.", __func__);
00731         goto exit_success;
00732     }
00733 
00734     /* CLI config is changed, clear local config and read new config. */
00735     clear_eq2_svc_gate();
00736     while (dax_visit_container(cop, &dop)) {
00737         if (!dax_get_stringr_by_name(dop, "name", name_str, sizeof(name_str))) {
00738             dax_error(dop, "Read name ERROR!");
00739             dax_release_object(&dop);
00740             break;
00741         }
00742         if (!dax_get_stringr_by_name(dop, "address", addr_str,
00743                 sizeof(addr_str))) {
00744             dax_error(cop, "Read address ERROR!");
00745             dax_release_object(&dop);
00746             break;
00747         }
00748         add_eq2_svc_gate(name_str, addr_str);
00749     }
00750 
00751 exit_success:
00752     dax_release_object(&cop);
00753 }
00754 
00759 static void
00760 read_eq2_svc_type (void)
00761 {
00762     ddl_handle_t *cop = NULL;
00763     ddl_handle_t *dop = NULL;
00764     const char *svc_type_config[] = { "sync", "equilibrium2", "service-type",
00765             NULL };
00766     char name_str[MAX_NAME_LEN];
00767     in_port_t port;
00768 
00769     if (!dax_get_object_by_path(NULL, svc_type_config, &cop, FALSE)) {
00770         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No service-type.", __func__);
00771         clear_eq2_svc_type();
00772         return;
00773     }
00774     if (!dax_is_changed(cop)) {
00775         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No change.", __func__);
00776         goto exit_success;
00777     }
00778 
00779     /* CLI config is changed, clear local config and read new config. */
00780     clear_eq2_svc_type();
00781     while (dax_visit_container(cop, &dop)) {
00782         if (!dax_get_stringr_by_name(dop, "name", name_str, sizeof(name_str))) {
00783             dax_error(dop, "Read name ERROR!");
00784             dax_release_object(&dop);
00785             break;
00786         }
00787         if (!dax_get_ushort_by_name(dop, "port", &port)) {
00788             dax_error(dop, "Read port ERROR!");
00789             dax_release_object(&dop);
00790             break;
00791         }
00792         add_eq2_svc_type(name_str, port);
00793     }
00794 
00795 exit_success:
00796     dax_release_object(&cop);
00797 }
00798 
00803 static void
00804 read_eq2_svr_group (void)
00805 {
00806     ddl_handle_t *cop_group = NULL;
00807     ddl_handle_t *dop_group = NULL;
00808     ddl_handle_t *cop_addr = NULL;
00809     ddl_handle_t *dop_addr = NULL;
00810     const char *svr_group_config[] = { "sync", "equilibrium2", "server-group",
00811             NULL };
00812     const char *svr_config[] = { "servers", NULL };
00813     char name_str[MAX_NAME_LEN];
00814     char addr_str[MAX_NAME_LEN];
00815     svr_addr_head_t addr_head;
00816     svr_addr_t *addr;
00817     int addr_count = 0;
00818 
00819     if (!dax_get_object_by_path(NULL, svr_group_config, &cop_group, FALSE)) {
00820         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No server-group.", __func__);
00821         clear_eq2_svr_group();
00822         return;
00823     }
00824     if (!dax_is_changed(cop_group)) {
00825         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No change.", __func__);
00826         goto exit_success;
00827     }
00828 
00829     /* CLI config is changed, clear local config and read new config. */
00830     clear_eq2_svr_group();
00831     LIST_INIT(&addr_head);
00832     while (dax_visit_container(cop_group, &dop_group)) {
00833         if (!dax_get_stringr_by_name(dop_group, "name", name_str,
00834                 sizeof(name_str))) {
00835             dax_error(dop_group, "Read name ERROR!");
00836             dax_release_object(&dop_group);
00837             goto exit_success;
00838         }
00839         if (!dax_get_object_by_path(dop_group, svr_config, &cop_addr, FALSE)) {
00840             dax_error(cop_addr, "Read address list ERROR!");
00841             dax_release_object(&dop_group);
00842             goto exit_success;
00843         }
00844         addr_count = 0;
00845         while (dax_visit_container(cop_addr, &dop_addr)) {
00846             if (!dax_get_stringr_by_name(dop_addr, "address", addr_str,
00847                     sizeof(addr_str))) {
00848                 dax_error(dop_addr, "Read address list ERROR!");
00849                 dax_release_object(&dop_addr);
00850                 dax_release_object(&cop_addr);
00851                 goto exit_success;
00852             }
00853             addr = calloc(1, sizeof(svr_addr_t));
00854             INSIST_ERR(addr != NULL);
00855             addr->addr = inet_addr(addr_str);
00856             LIST_INSERT_HEAD(&addr_head, addr, entry);
00857             addr_count++;
00858             EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s %s: %s", __func__,
00859                     name_str, addr_str);
00860         }
00861         add_eq2_svr_group(name_str, &addr_head, addr_count);
00862     }
00863 
00864 exit_success:
00865     dax_release_object(&cop_group);
00866 }
00867 
00881 static int 
00882 read_eq2_term (ddl_handle_t *top, svc_rule_t *rule)
00883 {
00884     const char *term_config[] = { "term", NULL };
00885     const char *from_config[] = { "from", NULL };
00886     const char *then_config[] = { "then", NULL };
00887     ddl_handle_t *cop_term = NULL;
00888     ddl_handle_t *dop_term = NULL;
00889     ddl_handle_t *dop_from = NULL;
00890     ddl_handle_t *dop_then = NULL;
00891     char term_name[MAX_NAME_LEN];
00892     char buf[MAX_NAME_LEN];
00893     char tog;
00894     svc_term_t *term;
00895 
00896     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s", __func__);
00897 
00898     if (!dax_get_object_by_path(top, term_config, &cop_term, FALSE)) {
00899         dax_error(top, "Read term ERROR.");
00900         return -1;
00901     }
00902 
00903     while (dax_visit_container(cop_term, &dop_term)) {
00904         if (!dax_get_stringr_by_name(dop_term, "name", term_name,
00905                 sizeof(term_name))) {
00906             dax_error(dop_term, "Read term name ERROR!");
00907             dax_release_object(&dop_term);
00908             dax_release_object(&cop_term);
00909             return -1;
00910         }
00911 
00912         term = calloc(1, sizeof(svc_term_t));
00913         INSIST_ERR(term != NULL);
00914         strlcpy(term->term_name, term_name, sizeof(term->term_name));
00915         LIST_INSERT_HEAD(&rule->rule_term_head, term, entry);
00916         rule->rule_term_count++;
00917 
00918         /* Read term match condition. */
00919         if (dax_get_object_by_path(dop_term, from_config, &dop_from, FALSE)) {
00920             if (dax_get_stringr_by_name(dop_from, "service-type", buf,
00921                     sizeof(buf))) {
00922                 term->term_match = TERM_FROM_SVC_TYPE;
00923                 strlcpy(term->term_match_val, buf,
00924                         sizeof(term->term_match_val));
00925             }
00926             if (dax_get_stringr_by_name(dop_from, "service-gate", buf,
00927                     sizeof(buf))) {
00928                 term->term_match = TERM_FROM_SVC_GATE;
00929                 strlcpy(term->term_match_val, buf,
00930                         sizeof(term->term_match_val));
00931             }
00932             if (dax_get_toggle_by_name(dop_from, "except", &tog)) {
00933                 term->term_match |= TERM_FROM_EXCEPT;
00934             }
00935             dax_release_object(&dop_from);
00936         }
00937 
00938         /* Read term action. */
00939         if (dax_get_object_by_path(dop_term, then_config, &dop_then, FALSE)) {
00940             if (dax_get_toggle_by_name(dop_then, "accept", &tog)) {
00941                 term->term_act = TERM_THEN_ACCEPT;
00942             } else if (dax_get_toggle_by_name(dop_then, "discard", &tog)) {
00943                 term->term_act = TERM_THEN_DISCARD;
00944             } else if (dax_get_stringr_by_name(dop_then, "server-group", buf,
00945                     sizeof(buf))) {
00946                 term->term_act = TERM_THEN_SVR_GROUP;
00947                 strlcpy(term->term_act_val, buf, sizeof(term->term_act_val));
00948             } else if (dax_get_stringr_by_name(dop_then, "service-gate", buf,
00949                     sizeof(buf))) {
00950                 term->term_act = TERM_THEN_SVC_GATE;
00951                 strlcpy(term->term_act_val, buf, sizeof(term->term_act_val));
00952             }
00953             dax_release_object(&dop_then);
00954         }
00955     }
00956     dax_release_object(&cop_term);
00957     return 0;
00958 }
00959 
00979 static int 
00980 read_eq2_rule (dax_walk_data_t *dwd, ddl_handle_t *dop, int action, void *data)
00981 {
00982     char rule_name[MAX_NAME_LEN];
00983     svc_rule_head_t *rule_head = data;
00984     svc_rule_t *rule;
00985 
00986     switch (action) {
00987     case DAX_ITEM_DELETE_ALL: /* All items was deleted. */
00988         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Delete all rules.", __func__);
00989         clear_eq2_svc_rule(rule_head);
00990         return DAX_WALK_OK;
00991         break;
00992 
00993     case DAX_ITEM_DELETE: /* One item was deleted. */
00994         if (!dax_get_stringr_by_dwd_ident(dwd, NULL, 0, rule_name,
00995                 sizeof(rule_name))) {
00996             dax_error(dop, "Read rule name ERROR!");
00997             return DAX_WALK_ABORT;
00998         }
00999         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Delete rule %s.", __func__,
01000                 rule_name);
01001         del_eq2_svc_rule(get_eq2_svc_rule(rule_head, rule_name));
01002         break;
01003 
01004     case DAX_ITEM_CHANGED:
01005         INSIST_ERR(dop != NULL);
01006         if (!dax_get_stringr_by_name(dop, "name", rule_name,
01007                 sizeof(rule_name))) {
01008             dax_error(dop, "Read rule name ERROR!");
01009             return DAX_WALK_ABORT;
01010         }
01011         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Change rule %s.", __func__,
01012                 rule_name);
01013 
01014         /* Clear the whole rule and reread it if anything is changed in it. */
01015         del_eq2_svc_rule(get_eq2_svc_rule(rule_head, rule_name));
01016 
01017         /* Create a new rule. */
01018         rule = calloc(1, sizeof(svc_rule_t));
01019         INSIST_ERR(rule != NULL);
01020         strlcpy(rule->rule_name, rule_name, sizeof(rule->rule_name));
01021         LIST_INSERT_HEAD(rule_head, rule, entry);
01022 
01023         if (read_eq2_term(dop, rule) < 0) {
01024             dax_error(NULL, "Read term ERROR!");
01025             return DAX_WALK_ABORT;
01026         }
01027         break;
01028 
01029     case DAX_ITEM_UNCHANGED:
01030         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: No change.", __func__);
01031         break;
01032 
01033     default:
01034         break;
01035     }
01036 
01037     return DAX_WALK_OK;
01038 }
01039 
01053 static uint16_t
01054 blob_cksum (void *buf, int len)
01055 {
01056     uint8_t *p = buf;
01057     uint32_t sum = 0;
01058 
01059     while (len > 1) {
01060         sum += (*p << 8) + *(p + 1);
01061         len -= 2;
01062         p += 2;
01063     }
01064     if (len == 1) {
01065         sum += (*p << 8);
01066     }
01067 
01068     while (sum >> 16)
01069         sum = (sum & 0xFFFF) + (sum >> 16);
01070 
01071     sum = ~sum;
01072 
01073     return (uint16_t)sum;
01074 }
01075 
01080 static void
01081 pack_svr_group_blob (void)
01082 {
01083     svr_group_t *group;
01084     blob_svr_group_t *blob_svr_group;
01085     in_addr_t *blob_addr;
01086     svr_addr_t *addr;
01087     int addr_count = 0;
01088     int blob_size = 0;
01089 
01090     /* Go through server group list to get total number of addresses. */
01091     LIST_FOREACH(group, &svr_group_head, entry) {
01092         addr_count += group->group_addr_count;
01093     }
01094     blob_size = sizeof(blob_svr_group_set_t) +
01095             svr_group_count * sizeof(blob_svr_group_t) +
01096             addr_count * sizeof(in_addr_t);
01097     blob_svr_group_set = calloc(1, blob_size);
01098     INSIST_ERR(blob_svr_group_set != NULL);
01099 
01100     /* Fill blob_svr_group_set. */
01101     blob_svr_group_set->gs_cksum = 0;
01102     blob_svr_group_set->gs_size = htons(blob_size);
01103     blob_svr_group_set->gs_count = htons(svr_group_count);
01104 
01105     /* Fill blob_svr_group. */
01106     blob_svr_group = blob_svr_group_set->gs_group;
01107     LIST_FOREACH(group, &svr_group_head, entry) {
01108         strlcpy(blob_svr_group->group_name, group->group_name,
01109                 sizeof(blob_svr_group->group_name));
01110         blob_svr_group->group_addr_count = htons(group->group_addr_count);
01111         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Group %s with %d addresses.",
01112             __func__, group->group_name, group->group_addr_count);
01113 
01114         /* Fill address list. */
01115         blob_addr = blob_svr_group->group_addr;
01116         LIST_FOREACH(addr, &group->group_addr_head, entry) {
01117             *blob_addr = addr->addr;
01118             EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s:      0x%08x", __func__,
01119                     addr->addr);
01120             blob_addr++;
01121         }
01122         blob_svr_group = (blob_svr_group_t *)blob_addr;
01123     }
01124     /* Not change byte order for checksum, cause it's only for RE. */
01125     blob_svr_group_set->gs_cksum = blob_cksum(blob_svr_group_set, blob_size);
01126 
01127     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: size %d, count %d.", __func__,
01128             blob_size, svr_group_count);
01129 }
01130 
01141 static blob_svc_set_t *
01142 pack_svc_set_blob (svc_set_t *ss)
01143 {
01144     svc_rule_head_t *svc_rule_head;
01145     svc_set_rule_t *ss_rule;
01146     svc_rule_t *rule;
01147     svc_term_t *term;
01148     int rule_count;
01149     int term_count;
01150     blob_svc_set_t *blob_ss = NULL;
01151     blob_rule_t *blob_rule;
01152     blob_term_t *blob_term;
01153     int blob_size = 0;
01154 
01155     switch (ss->ss_eq2_svc_id) {
01156     case EQ2_BALANCE_SVC:
01157         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: %s for balance service.", __func__,
01158                 ss->ss_name);
01159         svc_rule_head = &balance_rule_head;
01160         break;
01161     case EQ2_CLASSIFY_SVC:
01162         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: %s for classify service.", __func__,
01163                 ss->ss_name);
01164         svc_rule_head = &classify_rule_head;
01165         break;
01166     default:
01167         EQ2_LOG(TRACE_LOG_ERR, "%s: Unknown service %d!",
01168                 __func__, ss->ss_eq2_svc_id);
01169         return NULL;
01170     }
01171 
01172     /* Go through all rules to get the total number of terms. */
01173     term_count = 0;
01174     LIST_FOREACH(ss_rule, &ss->ss_rule_head, entry) {
01175         rule = get_eq2_svc_rule(svc_rule_head, ss_rule->rule_name);
01176         INSIST_ERR(rule != NULL);
01177         term_count += rule->rule_term_count;
01178     }
01179     rule_count = ss->ss_rule_count;
01180     blob_size = sizeof(blob_svc_set_t) + rule_count * sizeof(blob_rule_t) +
01181             term_count * sizeof(blob_term_t);
01182     blob_ss = calloc(1, blob_size);
01183     INSIST_ERR(blob_ss != NULL);
01184 
01185     /* Fill up service-set. */
01186     strlcpy(blob_ss->ss_name, ss->ss_name, sizeof(blob_ss->ss_name));
01187     strlcpy(blob_ss->ss_if_name, ss->ss_if_name, sizeof(blob_ss->ss_if_name));
01188     blob_ss->ss_size = htons(blob_size);
01189     blob_ss->ss_id = htons(ss->ss_id);
01190     blob_ss->ss_eq2_svc_id = ss->ss_eq2_svc_id;
01191     blob_ss->ss_rule_count = htons(rule_count);
01192 
01193     /* Fill up rules. */
01194     blob_rule = blob_ss->ss_rule;
01195     LIST_FOREACH(ss_rule, &ss->ss_rule_head, entry) {
01196         rule = get_eq2_svc_rule(svc_rule_head, ss_rule->rule_name);
01197         INSIST_ERR(rule != NULL);
01198         strlcpy(blob_rule->rule_name, ss_rule->rule_name,
01199                 sizeof(blob_rule->rule_name));
01200         blob_rule->rule_term_count = htons(rule->rule_term_count);
01201 
01202         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Rule %s with %d terms.",
01203                 __func__, ss_rule->rule_name, rule->rule_term_count);
01204 
01205         /* Fill up terms. */
01206         blob_term = blob_rule->rule_term;
01207         LIST_FOREACH(term, &rule->rule_term_head, entry) {
01208 
01209             /* Term name. */
01210             strlcpy(blob_term->term_name, term->term_name,
01211                     sizeof(blob_term->term_name));
01212 
01213             /* Term match condition. */
01214             blob_term->term_match_id = term->term_match;
01215             switch (blob_term->term_match_id) {
01216             case TERM_FROM_SVC_TYPE:
01217                 blob_term->term_match_port = htons(get_eq2_svc_type(
01218                         term->term_match_val));
01219                 EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Term %s, value %s, port %d.",
01220                         __func__, term->term_name, term->term_match_val,
01221                         get_eq2_svc_type(term->term_match_val));
01222                 break;
01223             case TERM_FROM_SVC_GATE:
01224                 blob_term->term_match_addr = get_eq2_svc_gate(
01225                         term->term_match_val);
01226                 EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Term %s, match value %s, "
01227                         "addr %x.",
01228                         __func__, term->term_name, term->term_match_val,
01229                         get_eq2_svc_gate(term->term_match_val));
01230                 break;
01231             default:
01232                 EQ2_LOG(TRACE_LOG_ERR, "%s: Unknown match ID!", __func__);
01233             }
01234 
01235             /* Term action. */
01236             blob_term->term_act_id = term->term_act;
01237             switch (blob_term->term_act_id) {
01238             case TERM_THEN_SVC_GATE:
01239                 blob_term->term_act_addr = get_eq2_svc_gate(
01240                         term->term_act_val);
01241                 EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Term %s, act value %s, "
01242                         "addr %x.",
01243                         __func__, term->term_name, term->term_act_val,
01244                         get_eq2_svc_gate(term->term_act_val));
01245                 break;
01246             case TERM_THEN_SVR_GROUP:
01247                 strlcpy(blob_term->term_act_group_name, term->term_act_val,
01248                         sizeof(blob_term->term_act_group_name));
01249                 EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Term %s, act value %s",
01250                         __func__, term->term_name, term->term_act_val);
01251                 break;
01252             default:
01253                 EQ2_LOG(TRACE_LOG_ERR, "%s: Unknown action ID!", __func__);
01254             }
01255             blob_term++;
01256         }
01257         blob_rule = (blob_rule_t *)blob_term;
01258     }
01259 
01260     /* Not change byte order for checksum, cause it's only for RE. */
01261     blob_ss->ss_cksum = blob_cksum(blob_ss, blob_size);
01262     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: blob size %d, rule %d.", __func__,
01263             blob_size, rule_count);
01264     return blob_ss;
01265 }
01266 
01277 static void
01278 add_svc_set_blob (blob_svc_set_node_t *blob_ss_node,
01279         junos_kcom_pub_ssrb_t *ssrb)
01280 {
01281     config_blob_key_t key;
01282 
01283     blob_ss_node->ss->ss_id = ntohs(ssrb->svc_set_id);
01284     blob_ss_node->ss->ss_gen_num = ntohl(ssrb->gen_num);
01285     blob_ss_node->ss->ss_svc_id = ntohl(ssrb->svc_id);
01286 
01287     bzero(&key, sizeof(key));
01288     strlcpy(key.key_name, blob_ss_node->ss->ss_name, sizeof(key.key_name));
01289     key.key_tag = CONFIG_BLOB_SVC_SET;
01290     key.key_plugin_id = blob_ss_node->ss->ss_eq2_svc_id;
01291     kcom_add_config_blob(&key, blob_ss_node->ss);
01292 
01293     /* Remove service-set config blob from the list and free it. */
01294     LIST_REMOVE(blob_ss_node, entry);
01295     free(blob_ss_node->ss);
01296     free(blob_ss_node);
01297 }
01298 
01305 static void
01306 config_post_proc (void)
01307 {
01308     svc_set_t *ss;
01309     blob_svc_set_t *blob_ss;
01310     blob_svc_set_node_t *blob_ss_node, *blob_ss_node_tmp;
01311     ssrb_node_t *ssrb_node;
01312     config_blob_key_t key;
01313 
01314     /* Rebuild the list of service interfaces. Server group config needs
01315      * to be sent to all service interfaces that are running balance
01316      * service.
01317      */
01318     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Build the list of service interface.",
01319             __func__);
01320     clear_svc_if();
01321     LIST_FOREACH(ss, &ss_head, entry) {
01322         add_svc_if(ss->ss_if_name);
01323     }
01324 
01325     /* Pack server group blob. */
01326     pack_svr_group_blob();
01327 
01328     /* Pack service-set blobs without SSRB info (service-set ID, service ID
01329      * and service-set generation number).
01330      */
01331     LIST_FOREACH(ss, &ss_head, entry) {
01332         blob_ss = pack_svc_set_blob(ss);
01333         if (blob_ss) {
01334             blob_ss_node = calloc(1, sizeof(blob_svc_set_node_t));
01335             INSIST_ERR(blob_ss_node != NULL);
01336             blob_ss_node->ss = blob_ss;
01337             LIST_INSERT_HEAD(&blob_ss_head, blob_ss_node, entry);
01338         }
01339     }
01340 
01341     /* Get all blobs in kernel and process them.
01342      * config_svc_set_blob_proc() and config_svr_group_blob_proc()
01343      * will be called to process respective blob.
01344      */
01345     kcom_get_config_blob();
01346 
01347     /* Check server group local blob, if it's still there, that means
01348      * either the server group configuration doesn't exist, or it has been
01349      * changed and the blob in kernel has been removed,
01350      * so add it to the kernel.
01351      */
01352     if (blob_svr_group_set) {
01353         bzero(&key, sizeof(key));
01354         strlcpy(key.key_name, "server-group", sizeof(key.key_name));
01355         key.key_tag = CONFIG_BLOB_SVR_GROUP;
01356         key.key_plugin_id = EQ2_BALANCE_SVC;
01357         kcom_add_config_blob(&key, blob_svr_group_set);
01358         free(blob_svr_group_set);
01359         blob_svr_group_set = NULL;
01360     }
01361 
01362     /* Add all packed service-set blobs that are still there. */
01363     LIST_FOREACH_SAFE(blob_ss_node, &blob_ss_head, entry, blob_ss_node_tmp) {
01364 
01365         /* SSRB info is needed here. */
01366         ssrb_node = config_get_ssrb(blob_ss_node->ss->ss_name);
01367 
01368         if (ssrb_node == NULL || ssrb_node->ssrb_state == SSRB_PENDING) {
01369 
01370             /* If SSRB doesn't exist, meaning this is a new service-set,
01371              * if SSRB is in 'pending' state, meaning service-set is changed,
01372              * an updated SSRB is expected. So just return for now,
01373              * this service-set blob will be added when receiving SSRB
01374              * by async handler later.
01375              */ 
01376             continue;
01377         }
01378 
01379         /* SSRB was received before reading config,
01380          * get info and add service-set blob.
01381          */
01382         add_svc_set_blob(blob_ss_node, &ssrb_node->ssrb);
01383     }
01384 
01385     /* Mark all updated SSRB as 'idle'. */
01386     LIST_FOREACH(ssrb_node, &ssrb_head, entry) {
01387         if (ssrb_node->ssrb_state == SSRB_UPDATED) {
01388             ssrb_node->ssrb_state = SSRB_IDLE;
01389         }
01390     }
01391 }
01392 
01404 static bool
01405 check_ssrb (junos_kcom_pub_ssrb_t *ssrb)
01406 {
01407     ssrb_svc_info_t *info;
01408     int i;
01409 
01410     /* Check service order list. */
01411     if (!ssrb->svc_order.fwd_flow_svc_order ||
01412             !ssrb->svc_order.rev_flow_svc_order) {
01413         return false;
01414     }
01415     info = ssrb->svc_order.fwd_flow_svc_order->elems;
01416     for (i = 0; i < ssrb->svc_order.fwd_flow_svc_order->num_elems; i++) {
01417         if ((strcmp(info->name, EQ2_BALANCE_SVC_NAME) == 0) ||
01418                 (strcmp(info->name, EQ2_CLASSIFY_SVC_NAME) == 0)) {
01419             return true;
01420         }
01421         info++;
01422     }
01423     info = ssrb->svc_order.rev_flow_svc_order->elems;
01424     for (i = 0; i < ssrb->svc_order.rev_flow_svc_order->num_elems; i++) {
01425         if ((strcmp(info->name, EQ2_BALANCE_SVC_NAME) == 0) ||
01426                 (strcmp(info->name, EQ2_CLASSIFY_SVC_NAME) == 0)) {
01427             return true;
01428         }
01429         info++;
01430     }
01431     return false;
01432 }
01433 
01434 /*** GLOBAL/EXTERNAL Functions ***/
01435 
01441 void
01442 config_init (void)
01443 {
01444     EQ2_TRACE(EQ2_TRACEFLAG_NORMAL, "%s: Initialize configuration.", __func__);
01445 
01446     LIST_INIT(&svc_gate_head);
01447     LIST_INIT(&svr_group_head);
01448     svr_group_count = 0;
01449     LIST_INIT(&svc_type_head);
01450     LIST_INIT(&balance_rule_head);
01451     LIST_INIT(&classify_rule_head);
01452     LIST_INIT(&ss_head);
01453     LIST_INIT(&ssrb_head);
01454     LIST_INIT(&blob_ss_head);
01455     LIST_INIT(&svc_if_head);
01456     svc_if_count = 0;
01457     blob_svr_group_set = NULL;
01458 }
01459 
01464 void
01465 config_clear (void)
01466 {
01467     clear_eq2_svc_gate();
01468     clear_eq2_svc_type();
01469     clear_eq2_svr_group();
01470     clear_eq2_svc_rule(&balance_rule_head);
01471     clear_eq2_svc_rule(&classify_rule_head);
01472     clear_svc_set();
01473     clear_ssrb_config();
01474 }
01475 
01480 void
01481 clear_ssrb_config (void)
01482 {
01483     ssrb_node_t *ssrb;
01484 
01485     while((ssrb = LIST_FIRST(&ssrb_head))) {
01486         LIST_REMOVE(ssrb, entry);
01487         free(ssrb);
01488     }
01489 }
01490 
01504 int
01505 config_ssrb_op (junos_kcom_pub_ssrb_t *ssrb, config_ssrb_op_t op)
01506 {
01507     ssrb_node_t *ssrb_node;
01508     blob_svc_set_node_t *blob_ss_node;
01509 
01510     if (!check_ssrb(ssrb)) {
01511         EQ2_TRACE(EQ2_TRACEFLAG_KCOM,
01512                 "%s: SSRB doesn't contain Equilibrium II service.", __func__); 
01513         return -1;
01514     }
01515 
01516     switch (op) {
01517     case CONFIG_SSRB_ADD:
01518         EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: Add SSRB %s, ID %d", __func__,
01519                 ssrb->svc_set_name, ssrb->svc_set_id); 
01520 
01521         /* Check for existance. */
01522         ssrb_node = config_get_ssrb(ssrb->svc_set_name);
01523         if (ssrb_node) {
01524             EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: SSRB exists.", __func__); 
01525             return -1;
01526         }
01527 
01528         /* Create SSRB config node and add it to the list. */
01529         ssrb_node = calloc(1, sizeof(ssrb_node_t));
01530         INSIST_ERR(ssrb_node != NULL);
01531 
01532         LIST_INSERT_HEAD(&ssrb_head, ssrb_node, entry);
01533         bcopy(ssrb, &ssrb_node->ssrb, sizeof(ssrb_node->ssrb));
01534 
01535         /* Fall to SSRB change. */
01536     case CONFIG_SSRB_CHANGE:
01537         EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: Change SSRB %s, ID %d", __func__,
01538                 ssrb->svc_set_name, ssrb->svc_set_id); 
01539 
01540         /* Check for existance. */
01541         ssrb_node = config_get_ssrb(ssrb->svc_set_name);
01542         if (!ssrb_node) {
01543             EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: SSRB doesn't exist.", __func__); 
01544             return -1;
01545         }
01546 
01547         /* Update SSRB. */
01548         bcopy(ssrb, &ssrb_node->ssrb, sizeof(ssrb_node->ssrb));
01549         ssrb_node->ssrb_state = SSRB_UPDATED;
01550 
01551         /* Get service-set blob containing balance rules.
01552          * If service-set blob doesn't exit, meaning this SSRB update was
01553          * received before reading config, then leave it there.
01554          * If service-set blob exists, meaning this SSRB update was received
01555          * after reading config and it's being expected, then add service-set
01556          * blob to kernel.
01557          */
01558         blob_ss_node = get_svc_set_blob_node(ssrb->svc_set_name,
01559                 EQ2_BALANCE_SVC);
01560         if (blob_ss_node) {
01561             add_svc_set_blob(blob_ss_node, ssrb);
01562             ssrb_node->ssrb_state = SSRB_IDLE;
01563         }
01564 
01565         /* Get service-set blob containing classify rules. */
01566         blob_ss_node = get_svc_set_blob_node(ssrb->svc_set_name,
01567                 EQ2_CLASSIFY_SVC);
01568         if (blob_ss_node) {
01569             add_svc_set_blob(blob_ss_node, ssrb);
01570             ssrb_node->ssrb_state = SSRB_IDLE;
01571         }
01572 
01573         break;
01574     case CONFIG_SSRB_DEL:
01575         EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: Delete SSRB %s, ID %d", __func__,
01576                 ssrb->svc_set_name, ssrb->svc_set_id); 
01577 
01578         /* Check for existance. */
01579         ssrb_node = config_get_ssrb(ssrb->svc_set_name);
01580         if (!ssrb_node) {
01581             EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: SSRB doesn't exist.", __func__); 
01582             return -1;
01583         }
01584 
01585         /* Remove SSRB from the list and free it. */
01586         LIST_REMOVE(ssrb_node, entry);
01587         free(ssrb_node);
01588         break;
01589     }
01590 
01591     return 0;
01592 }
01593 
01604 void
01605 config_svr_group_blob_proc (config_blob_key_t *key, void *blob)
01606 {
01607     blob_svr_group_set_t *blob_sg_set = blob;
01608 
01609     if (!blob_svr_group_set) {
01610         return;
01611     }
01612 
01613     if (blob_svr_group_set->gs_cksum == blob_sg_set->gs_cksum) {
01614         EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: Blob %s is not changed.",
01615                 __func__, key->key_name);
01616 
01617         /* Clear local server group blob, so it won't be added later. */
01618         free(blob_svr_group_set);
01619         blob_svr_group_set = NULL;
01620     } else {
01621         EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: Blob %s is changed %d -> %d.",
01622                 __func__, key->key_name, blob_sg_set->gs_cksum,
01623                 blob_svr_group_set->gs_cksum);
01624 
01625         /* Delete server group blob in kernel, new blob will be added later. */
01626         kcom_del_config_blob(key);
01627     }
01628 }
01629 
01640 void
01641 config_svc_set_blob_proc (config_blob_key_t *key, void *blob)
01642 {
01643     blob_svc_set_t *blob_ss = blob;
01644     blob_svc_set_node_t *blob_ss_node;
01645 
01646     /* Get service-set blob from configuration. */
01647     blob_ss_node = get_svc_set_blob_node(key->key_name, key->key_plugin_id);
01648 
01649     if (blob_ss_node && (blob_ss_node->ss->ss_cksum == blob_ss->ss_cksum)) {
01650         EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: Blob %s %d is not changed.",
01651                 __func__, key->key_name, key->key_plugin_id);
01652 
01653         /* Found local service-set blob and no change, delete it. */
01654         LIST_REMOVE(blob_ss_node, entry);
01655         free(blob_ss_node->ss);
01656         free(blob_ss_node);
01657 
01658     } else {
01659         if (blob_ss_node == NULL) {
01660             EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: %s %d is deleted.",
01661                     __func__, key->key_name, key->key_plugin_id);
01662         } else {
01663             EQ2_TRACE(EQ2_TRACEFLAG_KCOM, "%s: %s %d is changed %d -> %d.",
01664                     __func__, key->key_name, key->key_plugin_id,
01665                     blob_ss->ss_cksum, blob_ss_node->ss->ss_cksum);
01666         }
01667 
01668         /* Either did not found local service-set blob, which means it's
01669          * already removed from CLI configuration, then just delete the blob
01670          * from kernel,
01671          * or found the local blob but it's changed, then delete the blob from
01672          * kernel here and add the new blob to kernel after
01673          * kcom_get_config_blob() is done in config_post_proc().
01674          */
01675         kcom_del_config_blob(key);
01676     }
01677 }
01678 
01691 int
01692 eq2_config_read (int check)
01693 {
01694     ddl_handle_t *top = NULL;
01695     ddl_handle_t *dop = NULL;
01696     const char *svc_set_config[] = { "services", "service-set", NULL };
01697     const char *eq2_config[] = { "sync", "equilibrium2", NULL };
01698     const char *eq2_balance_rules_config[] = { "sync", "equilibrium2",
01699             "balance-rules", "rule", NULL };
01700     const char *eq2_classify_rules_config[] = { "sync", "equilibrium2",
01701             "classify-rules", "rule", NULL };
01702 
01703     /* Read trace options. */
01704     if (junos_trace_read_config(check, eq2_config)) {
01705         dax_error(NULL, "Parsing equilibrium2 traceoptions ERROR!");
01706         return -1;
01707     }
01708 
01709     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Start reading config.", __func__);
01710 
01711     /* Read [sync equilibrium2 service-gate]. */
01712     read_eq2_svc_gate();
01713 
01714     /* Read [sync equilibrium2 service-group]. */
01715     read_eq2_svr_group();
01716 
01717     /* Read [sync equilibrium2 service-type]. */
01718     read_eq2_svc_type();
01719 
01720     /* Read [sync equilibrium2 balance-rules]. */
01721     if (dax_get_object_by_path(NULL, eq2_balance_rules_config, &top, FALSE)) {
01722         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Read balance rules.", __func__);
01723         if (dax_walk_list(top, DAX_WALK_DELTA, read_eq2_rule,
01724                 &balance_rule_head) != DAX_WALK_OK) {
01725             dax_release_object(&top);
01726             dax_error(NULL, "Walk through equilibrium2 balance rules ERROR!");
01727             return -1;
01728         }
01729         dax_release_object(&top);
01730     }
01731 
01732     /* Read [sync equilibrium2 classify-rules]. */
01733     if (dax_get_object_by_path(NULL, eq2_classify_rules_config, &top, FALSE)) {
01734         EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Read classify rules.", __func__);
01735         if (dax_walk_list(top, DAX_WALK_DELTA, read_eq2_rule,
01736                 &classify_rule_head) != DAX_WALK_OK) {
01737             dax_release_object(&top);
01738             dax_error(NULL, "Walk through equilibrium2 classify rules ERROR!");
01739             return -1;
01740         }
01741         dax_release_object(&top);
01742     }
01743 
01744     /* Read service-set. */
01745     /* Clear all service-set before reading. */
01746     clear_svc_set();
01747 
01748     /* Get the head object of service-set list. */
01749     if (dax_get_object_by_path(NULL, svc_set_config, &top, FALSE)) {
01750         while (dax_visit_container(top, &dop)) {
01751 
01752             /* Always read all service-sets and load the service-sets that
01753              * contain EQ2 service, no matter they are changed or not,
01754              * cause application doesn't keep any service-set configuration.
01755              */
01756             read_svc_set(dop);
01757         }
01758         dax_release_object(&top);
01759     }
01760 
01761     if (!check) {
01762         config_post_proc();
01763     }
01764 
01765     EQ2_TRACE(EQ2_TRACEFLAG_CONF, "%s: Configuration was loaded.", __func__);
01766 
01767     return 0;
01768 }
01769 

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:58 2010 for SDK Your Net Corporation Equilibrium II: equilibrium2-mgmt 1.0 by Doxygen 1.5.1