monitube-data_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: monitube-data_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 
00023 #include "monitube-data_main.h"
00024 #include "monitube-data_config.h"
00025 #include "monitube-data_ha.h"
00026 #include "monitube-data_packet.h"
00027 #include <jnx/radix.h>
00028 
00029 /*** Constants ***/
00030 
00031 #define MAX_MON_NAME_LEN  256     
00032 
00033 /*** Data structures ***/
00034 
00035 
00040 typedef struct address_s {
00041     patnode    node;       
00042     in_addr_t  address;    
00043     in_addr_t  mask;       
00044 } address_t;
00045 
00046 
00051 typedef struct monitor_s {
00052     patnode    node;                   
00053     char       name[MAX_MON_NAME_LEN]; 
00054     uint32_t   rate;                   
00055     patroot *  addresses;              
00056 } monitor_t;
00057 
00058 
00063 typedef struct mirror_s {
00064     patnode    node;       
00065     in_addr_t  original;   
00066     in_addr_t  redirect;   
00067 } mirror_t;
00068 
00069 
00074 typedef struct prefix_s {
00075     rnode_t     rnode;        
00076     in_addr_t   prefix;       
00077     monitor_t * monitor;      
00078 } prefix_t;
00079 
00080 
00081 volatile boolean is_master; 
00082 
00083 static evContext       m_ctx;         
00084 static patroot         monitors_conf; 
00085 static patroot         mirrors_conf;  
00086 static radix_root_t    mon_prefixes;  
00087 static uint8_t         replication_interval;   
00088 
00089 static msp_spinlock_t  mir_conf_lock; 
00090 static msp_spinlock_t  mon_conf_lock; 
00091 
00092 
00097 static atomic_uint_t current_time;
00098 
00099 
00100 /*** STATIC/INTERNAL Functions ***/
00101 
00106 PATNODE_TO_STRUCT(mon_entry, monitor_t, node)
00107 
00108 
00109 
00113 PATNODE_TO_STRUCT(mir_entry, mirror_t, node)
00114 
00115 
00120 PATNODE_TO_STRUCT(address_entry, address_t, node)
00121 
00122 
00138 static void
00139 update_time(evContext ctx __unused,
00140             void * uap  __unused,
00141             struct timespec due __unused,
00142             struct timespec inter __unused)
00143 {
00144     atomic_add_uint(1, &current_time);
00145 }
00146 
00147 
00156 static uint8_t
00157 bit_count(uint32_t n)
00158 {
00159     register unsigned int tmp;
00160 
00161     tmp = n - ((n >> 1) & 033333333333)
00162             - ((n >> 2) & 011111111111);
00163     return ((tmp + (tmp >> 3)) & 030707070707) % 63;
00164 }
00165 
00166 
00173 static void
00174 delete_all_addresses(monitor_t * mon)
00175 {
00176     address_t * add = NULL;
00177     rnode_t * rn;
00178 
00179     while(NULL != (add =
00180         address_entry(patricia_find_next(mon->addresses, NULL)))) {
00181 
00182         if(!patricia_delete(mon->addresses, &add->node)) {
00183             LOG(LOG_ERR, "%s: Deleting address failed", __func__);
00184         }
00185 
00186         INSIST_ERR(msp_spinlock_lock(&mon_conf_lock) == MSP_OK);
00187 
00188         rn = radix_get(&mon_prefixes,
00189                 bit_count(add->mask), (uint8_t *)&add->address);
00190 
00191         if(rn == NULL) {
00192             LOG(LOG_ERR, "%s: Failed to find monitored prefix to remove from "
00193                     "monitor's rtree configuration", __func__);
00194         } else {
00195             radix_delete(&mon_prefixes, rn);
00196         }
00197 
00198 
00199         INSIST_ERR(msp_spinlock_unlock(&mon_conf_lock) == MSP_OK);
00200 
00201         free(add);
00202     }
00203 }
00204 
00205 
00206 /*** GLOBAL/EXTERNAL Functions ***/
00207 
00208 
00218 status_t
00219 init_config(evContext ctx)
00220 {
00221     m_ctx = ctx;
00222 
00223     is_master = FALSE;
00224 
00225     msp_spinlock_init(&mir_conf_lock);
00226     msp_spinlock_init(&mon_conf_lock);
00227 
00228     patricia_root_init(&monitors_conf, FALSE, MAX_MON_NAME_LEN, 0);
00229     patricia_root_init(&mirrors_conf, FALSE, sizeof(in_addr_t), 0);
00230 
00231     radix_init_root(&mon_prefixes);
00232 
00233     current_time = (atomic_uint_t)(time(NULL) - 1);
00234     replication_interval = 10; // default, but by the time it is used, it is set
00235 
00236     // cached system time
00237     if(evSetTimer(ctx, update_time, NULL, evNowTime(), evConsTime(1,0), NULL)) {
00238         LOG(LOG_EMERG, "%s: Failed to initialize an eventlib timer to generate "
00239             "the cached time", __func__);
00240         return EFAIL;
00241     }
00242 
00243     return SUCCESS;
00244 }
00245 
00246 
00256 void
00257 set_mastership(boolean state, in_addr_t master_addr)
00258 {
00259     static boolean do_once = TRUE;
00260 
00261     if(do_once) {
00262         do_once = FALSE;
00263         if(init_replication(master_addr, m_ctx) == SUCCESS) {
00264             is_master = state;
00265         }
00266         return;
00267     }
00268 
00269     // Only recall init_replication when changing
00270     if(state != is_master &&
00271         init_replication(master_addr, m_ctx) == SUCCESS) {
00272 
00273         is_master = state;
00274     }
00275 }
00276 
00277 
00284 void
00285 set_replication_interval(uint8_t interval)
00286 {
00287     replication_interval = interval;
00288 }
00289 
00290 
00296 uint8_t
00297 get_replication_interval(void)
00298 {
00299     return replication_interval;
00300 }
00301 
00302 
00309 time_t
00310 get_current_time(void)
00311 {
00312     return (time_t)current_time;
00313 }
00314 
00315 
00319 void
00320 clear_config(void)
00321 {
00322     clear_monitors_configuration();
00323     clear_mirrors_configuration();
00324 }
00325 
00326 
00330 void
00331 clear_monitors_configuration(void)
00332 {
00333     monitor_t * mon;
00334 
00335     while(NULL != (mon = mon_entry(patricia_find_next(&monitors_conf, NULL)))) {
00336 
00337         if(!patricia_delete(&monitors_conf, &mon->node)) {
00338             LOG(LOG_ERR, "%s: Deleting monitor failed", __func__);
00339         }
00340 
00341         delete_all_addresses(mon);
00342         patricia_root_delete(mon->addresses);
00343 
00344         free(mon);
00345     }
00346 
00347     clean_flows_with_any_monitor();
00348 }
00349 
00350 
00354 void
00355 clear_mirrors_configuration(void)
00356 {
00357     mirror_t * mir;
00358 
00359     INSIST_ERR(msp_spinlock_lock(&mir_conf_lock) == MSP_OK);
00360 
00361     while(NULL != (mir = mir_entry(patricia_find_next(&mirrors_conf, NULL)))) {
00362 
00363         if(!patricia_delete(&mirrors_conf, &mir->node)) {
00364                 LOG(LOG_ERR, "%s: Deleting mirror failed", __func__);
00365         }
00366 
00367         free(mir);
00368     }
00369 
00370     INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00371 
00372     clean_flows_with_any_mirror();
00373 }
00374 
00375 
00382 void
00383 delete_monitor(char * name)
00384 {
00385     monitor_t * mon;
00386 
00387     mon = mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
00388 
00389     if(mon == NULL) {
00390         LOG(LOG_WARNING, "%s: Could not find monitor to remove", __func__);
00391         return;
00392     }
00393 
00394     if(!patricia_delete(&monitors_conf, &mon->node)) {
00395         LOG(LOG_ERR, "%s: Deleting monitor failed", __func__);
00396         return;
00397     }
00398 
00399     delete_all_addresses(mon);
00400     patricia_root_delete(mon->addresses);
00401 
00402     free(mon);
00403 
00404     clean_flows_with_monitor(name);
00405 }
00406 
00407 
00414 void
00415 delete_mirror(in_addr_t from)
00416 {
00417     mirror_t * mir;
00418 
00419     INSIST_ERR(msp_spinlock_lock(&mir_conf_lock) == MSP_OK);
00420 
00421     mir = mir_entry(patricia_get(&mirrors_conf, sizeof(from), &from));
00422 
00423     if(mir == NULL) {
00424         INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00425         LOG(LOG_WARNING, "%s: Could not find mirror to remove", __func__);
00426         return;
00427     }
00428 
00429     if(!patricia_delete(&mirrors_conf, &mir->node)) {
00430         INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00431         LOG(LOG_ERR, "%s: Deleting mirror failed", __func__);
00432         return;
00433     }
00434     INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00435 
00436     clean_flows_with_mirror(from);
00437 
00438     free(mir);
00439 }
00440 
00441 
00454 void
00455 delete_address(char * name, in_addr_t addr, in_addr_t mask)
00456 {
00457     monitor_t * mon;
00458     address_t * address = NULL;
00459     rnode_t * rn;
00460 
00461     mon = mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
00462 
00463     if(mon == NULL) {
00464         LOG(LOG_WARNING, "%s: Could not find monitor matching given name",
00465                 __func__);
00466         return;
00467     }
00468 
00469     address = address_entry(patricia_get(mon->addresses,
00470                     sizeof(in_addr_t), &addr));
00471 
00472     if(address == NULL) {
00473         LOG(LOG_WARNING, "%s: Could not find address prefix to remove",
00474                 __func__);
00475         return;
00476     }
00477 
00478     if(!patricia_delete(mon->addresses, &address->node)) {
00479         LOG(LOG_ERR, "%s: Deleting address failed", __func__);
00480         return;
00481     }
00482 
00483     INSIST_ERR(msp_spinlock_lock(&mon_conf_lock) == MSP_OK);
00484 
00485     rn = radix_get(&mon_prefixes, bit_count(mask), (uint8_t *)&addr);
00486 
00487     if(rn == NULL) {
00488         LOG(LOG_ERR, "%s: Failed to find monitored prefix to remove from "
00489                 "monitor's rtree configuration", __func__);
00490     } else {
00491         radix_delete(&mon_prefixes, rn);
00492     }
00493 
00494     INSIST_ERR(msp_spinlock_unlock(&mon_conf_lock) == MSP_OK);
00495 
00496     clean_flows_in_monitored_prefix(name, addr, mask);
00497 
00498     free(address);
00499 }
00500 
00501 
00514 void
00515 add_address(char * name, in_addr_t addr, in_addr_t mask)
00516 {
00517     monitor_t * mon;
00518     address_t * address = NULL;
00519     prefix_t * prefix;
00520     struct in_addr paddr;
00521     char * tmp;
00522 
00523     mon = mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
00524 
00525     if(mon == NULL) {
00526         LOG(LOG_WARNING, "%s: Could not find monitor matching given name",
00527                 __func__);
00528         return;
00529     }
00530 
00531     address = calloc(1, sizeof(address_t));
00532     INSIST(address != NULL);
00533 
00534     address->address = addr;
00535     address->mask = mask;
00536 
00537     // Add to patricia tree
00538 
00539     if(!patricia_add(mon->addresses, &address->node)) {
00540         free(address);
00541         paddr.s_addr = addr;
00542         tmp = strdup(inet_ntoa(paddr));
00543         paddr.s_addr = mask;
00544         LOG(LOG_ERR, "%s: Cannot add address %s/%s as it conflicts with "
00545                 "another prefix in the same monitored-networks group (%s)",
00546                 __func__, tmp, inet_ntoa(paddr), mon->name);
00547         free(tmp);
00548         return;
00549     }
00550 
00551     prefix = calloc(1, sizeof(prefix_t));
00552     INSIST(prefix != NULL);
00553     prefix->prefix = addr;
00554     prefix->monitor = mon;
00555 
00556     radix_node_init(&prefix->rnode, bit_count(mask), 0);
00557 
00558     INSIST_ERR(msp_spinlock_lock(&mon_conf_lock) == MSP_OK);
00559 
00560     if(radix_add(&mon_prefixes, &prefix->rnode)) {
00561 
00562         LOG(LOG_ERR, "%s: Failed to add monitor prefix "
00563                 "to rtree configuration", __func__);
00564         free(prefix);
00565 
00566         patricia_delete(mon->addresses, &address->node);
00567         free(address);
00568     }
00569 
00570     INSIST_ERR(msp_spinlock_unlock(&mon_conf_lock) == MSP_OK);
00571 
00572     // clean any flows that might be unmonitored, but match this prefix,
00573     // so that they become monitored
00574     clean_flows_in_monitored_prefix(NULL, addr, mask);
00575 }
00576 
00577 
00587 void
00588 update_monitor(char * name, uint32_t rate)
00589 {
00590     monitor_t * mon;
00591 
00592     mon = mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
00593 
00594     if(mon == NULL) {
00595         mon = calloc(1, sizeof(monitor_t));
00596         INSIST(mon != NULL);
00597         strncpy(mon->name, name, MAX_MON_NAME_LEN);
00598 
00599         // Add to patricia tree
00600         patricia_node_init_length(&mon->node, strlen(name) + 1);
00601 
00602         if(!patricia_add(&monitors_conf, &mon->node)) {
00603             LOG(LOG_ERR, "%s: Failed to add "
00604                     "monitor to configuration", __func__);
00605             free(mon);
00606             return;
00607         }
00608 
00609         // init addresses
00610         mon->addresses = patricia_root_init(NULL, FALSE, sizeof(in_addr_t), 0);
00611     }
00612 
00613     if(mon->rate != rate) {
00614         mon->rate = rate;
00615         clean_flows_with_monitor(name); // we don't reset stats, just clean
00616     }
00617 }
00618 
00619 
00629 void
00630 update_mirror(in_addr_t from, in_addr_t to)
00631 {
00632     boolean is_new = FALSE;
00633     mirror_t * mir;
00634 
00635     INSIST_ERR(msp_spinlock_lock(&mir_conf_lock) == MSP_OK);
00636 
00637     mir = mir_entry(patricia_get(&mirrors_conf, sizeof(from), &from));
00638 
00639     if(mir == NULL) {
00640         mir = calloc(1, sizeof(mirror_t));
00641         INSIST(mir != NULL);
00642         mir->original = from;
00643 
00644         if(!patricia_add(&mirrors_conf, &mir->node)) {
00645             LOG(LOG_ERR, "%s: Failed to add "
00646                     "mirror to configuration", __func__);
00647             free(mir);
00648             INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00649             return;
00650         }
00651         is_new = TRUE;
00652     }
00653 
00654     mir->redirect = to;
00655 
00656     INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00657 
00658     if(!is_new) {
00659         redirect_flows_with_mirror(from, to);
00660     }
00661 }
00662 
00663 
00675 uint32_t
00676 get_monitored_rate(in_addr_t address, char ** name)
00677 {
00678     rnode_t * rn;
00679     struct in_addr tmp;
00680     prefix_t * prefix;
00681     uint32_t result = 0;
00682 
00683     tmp.s_addr = address;
00684     LOG(LOG_INFO, "%s: Looking up rate for %s", __func__, inet_ntoa(tmp));
00685 
00686     INSIST_ERR(msp_spinlock_lock(&mon_conf_lock) == MSP_OK);
00687 
00688     rn = radix_lookup(&mon_prefixes, (uint8_t *)&address);
00689 
00690     if(rn == NULL) {
00691         INSIST_ERR(msp_spinlock_unlock(&mon_conf_lock) == MSP_OK);
00692         return 0;
00693     }
00694 
00695     prefix = (prefix_t *)((uint8_t *)rn - offsetof(prefix_t, rnode));
00696 
00697     *name = prefix->monitor->name;
00698     result = prefix->monitor->rate;
00699 
00700     INSIST_ERR(msp_spinlock_unlock(&mon_conf_lock) == MSP_OK);
00701 
00702     LOG(LOG_INFO, "%s: Match for flow to %s. Name: %s, Rate: %d", __func__,
00703             inet_ntoa(tmp), *name, result);
00704 
00705     return result;
00706 }
00707 
00708 
00717 in_addr_t
00718 get_mirror(in_addr_t address)
00719 {
00720     mirror_t * mir;
00721     in_addr_t result = 0;
00722 
00723     INSIST_ERR(msp_spinlock_lock(&mir_conf_lock) == MSP_OK);
00724 
00725     mir = mir_entry(patricia_get(&mirrors_conf, sizeof(address), &address));
00726 
00727     if(mir != NULL) {
00728         result = mir->redirect;
00729     }
00730 
00731     INSIST_ERR(msp_spinlock_unlock(&mir_conf_lock) == MSP_OK);
00732 
00733     return result;
00734 }

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:27:02 2010 for SDK Your Net Corporation Monitube IPTV Monitoring Example: monitube-data 1.0 by Doxygen 1.5.1