00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00021 #include <sync/common.h>
00022 #include <ddl/dax.h>
00023 #include <jnx/pconn.h>
00024 #include "monitube-mgmt_config.h"
00025 #include "monitube-mgmt_conn.h"
00026 #include "monitube-mgmt_logging.h"
00027
00028 #include MONITUBE_OUT_H
00029
00030
00031
00032 #define MAX_FLOW_AGE 300
00033
00034
00035
00036
00037
00038 static patroot monitors_conf;
00039 static patroot mirrors_conf;
00040 static monitor_t * current_monitor = NULL;
00041 static uint8_t replication_interval;
00042 static evContext m_ctx;
00043
00044
00045
00050 PATNODE_TO_STRUCT(mon_entry, monitor_t, node)
00051
00052
00053
00057 PATNODE_TO_STRUCT(mir_entry, mirror_t, node)
00058
00059
00064 PATNODE_TO_STRUCT(address_entry, address_t, node)
00065
00066
00071 PATNODE_TO_STRUCT(fs_entry, flowstat_t, node)
00072
00073
00083 static void
00084 update_address(in_addr_t addr, in_addr_t mask)
00085 {
00086 address_t * address = NULL;
00087 struct in_addr paddr;
00088 char * tmp;
00089
00090 INSIST_ERR(current_monitor != NULL);
00091
00092 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00093
00094 address = calloc(1, sizeof(address_t));
00095 INSIST(address != NULL);
00096
00097 address->address = addr;
00098 address->mask = mask;
00099
00100
00101
00102 if(!patricia_add(current_monitor->addresses, &address->node)) {
00103 free(address);
00104 paddr.s_addr = addr;
00105 tmp = strdup(inet_ntoa(paddr));
00106 paddr.s_addr = mask;
00107 LOG(TRACE_LOG_ERR, "%s: Cannot add address %s/%s as it conflicts with "
00108 "another address in the same monitored-networks group (%s)",
00109 __func__, tmp, inet_ntoa(paddr), current_monitor->name);
00110 free(tmp);
00111 }
00112
00113 notify_address_update(current_monitor->name, addr, mask);
00114 }
00115
00116
00129 static monitor_t *
00130 update_monitor(const char * name, uint32_t rate)
00131 {
00132 monitor_t * mon;
00133
00134 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00135
00136 mon = mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
00137
00138 if(mon == NULL) {
00139 mon = calloc(1, sizeof(monitor_t));
00140 INSIST(mon != NULL);
00141 strncpy(mon->name, name, MAX_MON_NAME);
00142
00143
00144 patricia_node_init_length(&mon->node, strlen(name) + 1);
00145
00146 if(!patricia_add(&monitors_conf, &mon->node)) {
00147 LOG(TRACE_LOG_ERR, "%s: Failed to add "
00148 "monitor to configuration", __func__);
00149 free(mon);
00150 return NULL;
00151 }
00152
00153
00154 mon->addresses = patricia_root_init(NULL, FALSE, sizeof(in_addr_t), 0);
00155
00156
00157 mon->flow_stats = patricia_root_init(NULL, FALSE,
00158 sizeof(in_addr_t) + (3 * sizeof(uint16_t)), 0);
00159 }
00160
00161 if(mon->rate != rate) {
00162 mon->rate = rate;
00163 notify_monitor_update(name, rate);
00164 }
00165
00166 return mon;
00167 }
00168
00169
00179 static void
00180 update_mirror(in_addr_t from, in_addr_t to)
00181 {
00182 mirror_t * mir;
00183
00184 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00185
00186 mir = mir_entry(patricia_get(&mirrors_conf, sizeof(from), &from));
00187
00188 if(mir == NULL) {
00189 mir = calloc(1, sizeof(mirror_t));
00190 INSIST(mir != NULL);
00191 mir->original = from;
00192
00193 if(!patricia_add(&mirrors_conf, &mir->node)) {
00194 LOG(TRACE_LOG_ERR, "%s: Failed to add "
00195 "mirror to configuration", __func__);
00196 free(mir);
00197 return;
00198 }
00199 }
00200
00201
00202 if(mir->redirect != to) {
00203 mir->redirect = to;
00204 notify_mirror_update(from, to);
00205 }
00206 }
00207
00208
00215 static void
00216 delete_all_addresses(boolean notify)
00217 {
00218 address_t * add = NULL;
00219
00220 INSIST_ERR(current_monitor != NULL);
00221
00222 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00223
00224 while(NULL != (add =
00225 address_entry(patricia_find_next(current_monitor->addresses, NULL)))) {
00226
00227 if(!patricia_delete(current_monitor->addresses, &add->node)) {
00228 LOG(TRACE_LOG_ERR, "%s: Deleting address failed", __func__);
00229 continue;
00230 }
00231
00232 free(add);
00233 }
00234
00235 if(notify) {
00236
00237
00238 notify_monitor_delete(current_monitor->name);
00239 }
00240 }
00241
00242
00249 static void
00250 delete_all_flowstats(monitor_t * mon)
00251 {
00252 flowstat_t * fs = NULL;
00253
00254 INSIST_ERR(mon != NULL);
00255
00256 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00257
00258 while(NULL != (fs = fs_entry(patricia_find_next(mon->flow_stats, NULL)))) {
00259
00260 if(evTestID(fs->timer_id)) {
00261 evClearTimer(m_ctx, fs->timer_id);
00262 }
00263
00264 if(!patricia_delete(mon->flow_stats, &fs->node)) {
00265 LOG(TRACE_LOG_ERR, "%s: Deleting flowstat failed", __func__);
00266 continue;
00267 }
00268
00269 free(fs);
00270 }
00271 }
00272
00273
00277 static void
00278 delete_all_monitors(void)
00279 {
00280 monitor_t * mon;
00281
00282 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00283
00284 while(NULL != (mon = mon_entry(patricia_find_next(&monitors_conf, NULL)))) {
00285
00286 current_monitor = mon;
00287 delete_all_addresses(FALSE);
00288 patricia_root_delete(mon->addresses);
00289 delete_all_flowstats(mon);
00290 patricia_root_delete(mon->flow_stats);
00291
00292 if(!patricia_delete(&monitors_conf, &mon->node)) {
00293 LOG(TRACE_LOG_ERR, "%s: Deleting monitor failed", __func__);
00294 continue;
00295 }
00296
00297 free(mon);
00298 }
00299
00300 current_monitor = NULL;
00301
00302 notify_delete_all_monitors();
00303 }
00304
00305
00309 static void
00310 delete_all_mirrors(void)
00311 {
00312 mirror_t * mir;
00313
00314 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00315
00316 while(NULL != (mir = mir_entry(patricia_find_next(&mirrors_conf, NULL)))) {
00317
00318 if(!patricia_delete(&mirrors_conf, &mir->node)) {
00319 LOG(TRACE_LOG_ERR, "%s: Deleting mirror failed", __func__);
00320 continue;
00321 }
00322
00323 free(mir);
00324 }
00325
00326 notify_delete_all_mirrors();
00327 }
00328
00329
00339 static void
00340 delete_address(in_addr_t addr, in_addr_t mask)
00341 {
00342 address_t * address = NULL;
00343
00344 INSIST_ERR(current_monitor != NULL);
00345
00346 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00347
00348 address = address_entry(patricia_get(current_monitor->addresses,
00349 sizeof(in_addr_t), &addr));
00350
00351 if(address == NULL) {
00352 LOG(TRACE_LOG_ERR, "%s: Could not find address to delete",__func__);
00353 return;
00354 }
00355
00356 notify_address_delete(current_monitor->name, addr, mask);
00357
00358 if(!patricia_delete(current_monitor->addresses, &address->node)) {
00359 LOG(TRACE_LOG_ERR, "%s: Deleting address failed", __func__);
00360 return;
00361 }
00362
00363 free(address);
00364
00365
00366 }
00367
00368
00375 static void
00376 delete_monitor(monitor_t * mon)
00377 {
00378 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00379
00380 current_monitor = mon;
00381 delete_all_addresses(FALSE);
00382 patricia_root_delete(mon->addresses);
00383 delete_all_flowstats(mon);
00384 patricia_root_delete(mon->flow_stats);
00385 current_monitor = NULL;
00386
00387 notify_monitor_delete(mon->name);
00388
00389 if(!patricia_delete(&monitors_conf, &mon->node)) {
00390 LOG(TRACE_LOG_ERR, "%s: Deleting monitor failed", __func__);
00391 return;
00392 }
00393
00394 free(mon);
00395 }
00396
00397
00404 static void
00405 delete_mirror(in_addr_t from)
00406 {
00407 mirror_t * mir;
00408
00409 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00410
00411 mir = mir_entry(patricia_get(&mirrors_conf, sizeof(from), &from));
00412
00413 if(mir == NULL) {
00414 LOG(TRACE_LOG_ERR, "%s: Could not find mirror to delete", __func__);
00415 return;
00416 }
00417
00418 notify_mirror_delete(from);
00419
00420 if(!patricia_delete(&mirrors_conf, &mir->node)) {
00421 LOG(TRACE_LOG_ERR, "%s: Deleting mirror failed", __func__);
00422 return;
00423 }
00424
00425 free(mir);
00426 }
00427
00428
00448 static int
00449 parse_addresses(dax_walk_data_t * dwd,
00450 ddl_handle_t * dop,
00451 int action,
00452 void * data)
00453 {
00454 char ip_str[32], * tmpstr, *tmpip;
00455 struct in_addr tmp;
00456 in_addr_t addr, prefix;
00457 int check = *((int *)data), mask;
00458
00459 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00460
00461 if(action == DAX_ITEM_DELETE_ALL) {
00462
00463 delete_all_addresses(TRUE);
00464 return DAX_WALK_OK;
00465 }
00466
00467 INSIST(dop != NULL);
00468
00469 switch(action) {
00470
00471 case DAX_ITEM_DELETE:
00472
00473
00474
00475
00476 if(!dax_get_stringr_by_dwd_ident(dwd, NULL, 0, ip_str, sizeof(ip_str))){
00477 dax_error(dop, "Failed to parse IP address and prefix on delete");
00478 return DAX_WALK_ABORT;
00479 }
00480
00481
00482 tmpip = strdup(ip_str);
00483 tmpstr = strtok(tmpip, "/");
00484
00485 if(inet_aton(tmpstr, &tmp) != 1) {
00486 dax_error(dop, "Failed to parse prefix address portion: %s",
00487 ip_str);
00488 return DAX_WALK_ABORT;
00489 }
00490 addr = tmp.s_addr;
00491
00492
00493 tmpstr = strtok(NULL, "/");
00494
00495 errno = 0;
00496 mask = (int)strtol(tmpstr, (char **)NULL, 10);
00497 if(errno) {
00498 dax_error(dop, "Failed to parse prefix mask portion: %s", ip_str);
00499 return DAX_WALK_ABORT;
00500 }
00501 if(mask < 0 || mask > 32) {
00502 dax_error(dop, "Mask bits must be in range of 0-32: %s", ip_str);
00503 return DAX_WALK_ABORT;
00504 }
00505
00506 if(mask == 32) {
00507 prefix = 0xFFFFFFFF;
00508 } else {
00509 prefix = (1 << mask) - 1;
00510 prefix = htonl(prefix);
00511 }
00512
00513 free(tmpip);
00514
00515 if(!check) {
00516 delete_address(addr, prefix);
00517 }
00518
00519 break;
00520
00521 case DAX_ITEM_CHANGED:
00522
00523
00524 if(!dax_get_ipv4prefixmandatory_by_name(dop,
00525 DDLNAME_MONITORED_NETWORKS_ADDRESS, &addr, &prefix)) {
00526 dax_error(dop, "Failed to parse IP address and prefix");
00527 return DAX_WALK_ABORT;
00528 }
00529
00530 if(((~prefix) & addr) != 0) {
00531 dax_error(dop, "Host bits in address must be zero");
00532 return DAX_WALK_ABORT;
00533 }
00534
00535 if(!check) {
00536 update_address(addr, prefix);
00537 }
00538
00539 break;
00540
00541 case DAX_ITEM_UNCHANGED:
00542 junos_trace(MONITUBE_TRACEFLAG_CONF,
00543 "%s: DAX_ITEM_UNCHANGED observed", __func__);
00544 break;
00545
00546 default:
00547 break;
00548 }
00549
00550 return DAX_WALK_OK;
00551 }
00552
00553
00572 static int
00573 parse_monitors(dax_walk_data_t * dwd,
00574 ddl_handle_t * dop,
00575 int action,
00576 void * data)
00577 {
00578 char monitor_name[MAX_MON_NAME];
00579 uint32_t rate;
00580 monitor_t * mon;
00581 ddl_handle_t * mon_nets_dop;
00582 int check = *((int *)data);
00583
00584 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00585
00586 switch (action) {
00587
00588 case DAX_ITEM_DELETE_ALL:
00589
00590
00591 delete_all_monitors();
00592 return DAX_WALK_OK;
00593
00594 break;
00595
00596 case DAX_ITEM_DELETE:
00597
00598
00599 if (!dax_get_stringr_by_dwd_ident(dwd, NULL, 0,
00600 monitor_name, sizeof(monitor_name))) {
00601 dax_error(dop, "Failed to parse a monitor name");
00602 return DAX_WALK_ABORT;
00603 }
00604
00605 if(check) {
00606 break;
00607 }
00608
00609 mon = mon_entry(patricia_get(&monitors_conf,
00610 strlen(monitor_name) + 1, monitor_name));
00611 if(mon != NULL) {
00612 delete_monitor(mon);
00613 }
00614
00615 break;
00616
00617 case DAX_ITEM_CHANGED:
00618
00619 INSIST_ERR(dop != NULL);
00620
00621
00622
00623 if (!dax_get_stringr_by_name(dop, DDLNAME_MONITOR_MONITOR_NAME,
00624 monitor_name, sizeof(monitor_name))) {
00625 dax_error(dop, "Failed to parse monitor name");
00626 return DAX_WALK_ABORT;
00627 }
00628
00629
00630
00631 if (!dax_get_uint_by_name(dop, DDLNAME_MONITOR_RATE, &rate)) {
00632 dax_error(dop, "Failed to parse rate");
00633 return DAX_WALK_ABORT;
00634 }
00635
00636 if(!dax_get_object_by_name(dop, DDLNAME_MONITORED_NETWORKS,
00637 &mon_nets_dop, FALSE)) {
00638
00639 dax_error(dop, "Failed to parse monitored-networks (required)");
00640 return DAX_WALK_ABORT;
00641
00642 } else {
00643
00644
00645 if(!check) {
00646 current_monitor = update_monitor(monitor_name, rate);
00647 if(current_monitor == NULL) {
00648 dax_release_object(&mon_nets_dop);
00649 return DAX_WALK_ABORT;
00650 }
00651 }
00652
00653 if(dax_walk_list(mon_nets_dop, DAX_WALK_DELTA, parse_addresses,data)
00654 != DAX_WALK_OK) {
00655
00656 dax_release_object(&mon_nets_dop);
00657 current_monitor = NULL;
00658 return DAX_WALK_ABORT;
00659 }
00660 }
00661
00662 current_monitor = NULL;
00663 dax_release_object(&mon_nets_dop);
00664
00665 break;
00666
00667 case DAX_ITEM_UNCHANGED:
00668 junos_trace(MONITUBE_TRACEFLAG_CONF,
00669 "%s: DAX_ITEM_UNCHANGED observed", __func__);
00670 break;
00671
00672 default:
00673 break;
00674 }
00675
00676 return DAX_WALK_OK;
00677 }
00678
00679
00680
00699 static int
00700 parse_mirrors(dax_walk_data_t * dwd,
00701 ddl_handle_t * dop,
00702 int action,
00703 void * data)
00704 {
00705 in_addr_t mirror_from;
00706 in_addr_t mirror_to;
00707 char ip_str[INET_ADDRSTRLEN];
00708 struct in_addr tmp;
00709 int check = *((int *)data);
00710 int addr_fam;
00711
00712 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00713
00714 switch (action) {
00715
00716 case DAX_ITEM_DELETE_ALL:
00717
00718
00719 delete_all_mirrors();
00720 return DAX_WALK_OK;
00721
00722 break;
00723
00724 case DAX_ITEM_DELETE:
00725
00726
00727 if (!dax_get_stringr_by_dwd_ident(dwd, NULL, 0,
00728 ip_str, sizeof(ip_str))) {
00729 dax_error(dop, "Failed to parse mirror address");
00730 return DAX_WALK_ABORT;
00731 }
00732 if(inet_aton(ip_str, &tmp) != 1) {
00733 dax_error(dop, "Failed to parse mirror IP from: %s", ip_str);
00734 return DAX_WALK_ABORT;
00735 }
00736 mirror_from = tmp.s_addr;
00737
00738 if(!check) {
00739 delete_mirror(mirror_from);
00740 }
00741
00742 break;
00743
00744 case DAX_ITEM_CHANGED:
00745
00746 INSIST_ERR(dop != NULL);
00747
00748
00749
00750 if(!dax_get_ipaddr_by_name(dop, DDLNAME_MIRROR_MIRRORED_ADDRESS,
00751 &addr_fam, &mirror_from, sizeof(mirror_from)) ||
00752 addr_fam != AF_INET) {
00753 dax_error(dop, "Failed to parse mirror IP");
00754 return DAX_WALK_ABORT;
00755 }
00756
00757 if(!dax_get_ipaddr_by_name(dop, DDLNAME_MIRROR_DESTINATION,
00758 &addr_fam, &mirror_to, sizeof(mirror_to)) ||
00759 addr_fam != AF_INET) {
00760 dax_error(dop, "Failed to parse mirror destination IP");
00761 return DAX_WALK_ABORT;
00762 }
00763
00764
00765 if(!check) {
00766 update_mirror(mirror_from, mirror_to);
00767 }
00768
00769 break;
00770
00771 case DAX_ITEM_UNCHANGED:
00772 junos_trace(MONITUBE_TRACEFLAG_CONF,
00773 "%s: DAX_ITEM_UNCHANGED observed", __func__);
00774 break;
00775
00776 default:
00777 break;
00778 }
00779
00780 return DAX_WALK_OK;
00781 }
00782
00783
00799 static void
00800 age_out_flow_stat(evContext ctx __unused, void * uap,
00801 struct timespec due __unused, struct timespec inter __unused)
00802 {
00803 flowstat_t * fs = (flowstat_t *)uap;
00804
00805 INSIST_ERR(fs != NULL);
00806
00807 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
00808
00809 if(evTestID(fs->timer_id)) {
00810 evClearTimer(m_ctx, fs->timer_id);
00811 }
00812
00813 if(!patricia_delete(fs->mon->flow_stats, &fs->node)) {
00814 LOG(TRACE_LOG_ERR, "%s: Deleting flowstat failed", __func__);
00815 return;
00816 }
00817
00818 free(fs);
00819 }
00820
00821
00822
00823
00824
00828 void
00829 init_config(evContext ctx)
00830 {
00831 m_ctx = ctx;
00832 replication_interval = 0;
00833
00834 patricia_root_init(&monitors_conf, FALSE, MAX_MON_NAME, 0);
00835 patricia_root_init(&mirrors_conf, FALSE, sizeof(in_addr_t), 0);
00836 }
00837
00838
00842 void
00843 clear_config(void)
00844 {
00845 delete_all_monitors();
00846 delete_all_mirrors();
00847 }
00848
00849
00860 int
00861 monitube_config_read(int check)
00862 {
00863 const char * monitube_config[] =
00864 {DDLNAME_SYNC, DDLNAME_SYNC_MONITUBE, NULL};
00865
00866 ddl_handle_t * top = NULL, * mon_dop = NULL, * mir_dop = NULL;
00867 uint8_t old_ri;
00868
00869 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s: Starting monitube "
00870 "configuration load", __func__);
00871
00872
00873
00874 if (!dax_get_object_by_path(NULL, monitube_config, &top, FALSE)) {
00875
00876 junos_trace(MONITUBE_TRACEFLAG_CONF,
00877 "%s: Cleared monitube configuration", __func__);
00878
00879 clear_config();
00880 return SUCCESS;
00881 } else {
00882 if(dax_get_object_by_name(top, DDLNAME_MONITOR, &mon_dop, FALSE)) {
00883 if(dax_walk_list(mon_dop, DAX_WALK_DELTA, parse_monitors, &check)
00884 != DAX_WALK_OK) {
00885
00886 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s: walk monitors "
00887 "list in sampling configuration failed", __func__);
00888 goto failed;
00889 }
00890 } else {
00891 delete_all_monitors();
00892 }
00893
00894 if(dax_get_object_by_name(top, DDLNAME_MIRROR, &mir_dop, FALSE)) {
00895 if(dax_walk_list(mir_dop, DAX_WALK_DELTA, parse_mirrors, &check)
00896 != DAX_WALK_OK) {
00897 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s: walk mirrors list in "
00898 "sampling configuration failed", __func__);
00899 goto failed;
00900 }
00901 } else {
00902 delete_all_mirrors();
00903 }
00904
00905 if(mon_dop == NULL && mir_dop == NULL) {
00906 dax_error(top, "Cannot have empty monitube service configuration");
00907 goto failed;
00908 }
00909
00910 old_ri = replication_interval;
00911
00912 dax_get_ubyte_by_name(top,
00913 DDLNAME_SYNC_MONITUBE_REPLICATION_INTERVAL,
00914 &replication_interval);
00915
00916 if(old_ri != replication_interval) {
00917 notify_replication_interval(replication_interval);
00918 }
00919
00920 dax_release_object(&top);
00921 }
00922
00923
00924 if(!check) {
00925
00926 process_notifications();
00927 }
00928
00929 junos_trace(MONITUBE_TRACEFLAG_CONF,
00930 "%s: Loaded monitube configuration", __func__);
00931
00932 return SUCCESS;
00933
00934 failed:
00935
00936 if(mon_dop)
00937 dax_release_object(&mon_dop);
00938
00939 if(mir_dop)
00940 dax_release_object(&mir_dop);
00941
00942 if(top)
00943 dax_release_object(&top);
00944
00945 return EFAIL;
00946 }
00947
00948
00954 uint8_t
00955 get_replication_interval(void)
00956 {
00957 return replication_interval;
00958 }
00959
00968 monitor_t *
00969 next_monitor(monitor_t * data)
00970 {
00971 return mon_entry(
00972 patricia_find_next(&monitors_conf, (data ? &(data->node) : NULL)));
00973 }
00974
00975
00984 mirror_t *
00985 next_mirror(mirror_t * data)
00986 {
00987 return mir_entry(
00988 patricia_find_next(&mirrors_conf, (data ? &(data->node) : NULL)));
00989 }
00990
00991
01004 address_t *
01005 next_address(monitor_t * mon, address_t * data)
01006 {
01007 return address_entry(patricia_find_next(mon->addresses,
01008 (data ? &(data->node) : NULL)));
01009 }
01010
01011
01024 flowstat_t *
01025 next_flowstat(monitor_t * mon, flowstat_t * data)
01026 {
01027 return fs_entry(patricia_find_next(mon->flow_stats,
01028 (data ? &(data->node) : NULL)));
01029 }
01030
01031
01040 monitor_t *
01041 find_monitor(char * name)
01042 {
01043 return mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
01044 }
01045
01046
01071 void
01072 set_flow_stat(uint16_t fpc_slot,
01073 uint16_t pic_slot,
01074 const char * name,
01075 in_addr_t flow_addr,
01076 uint16_t flow_port,
01077 double mdi_df,
01078 uint32_t mdi_mlr)
01079 {
01080 monitor_t * mon;
01081 flowstat_t * fs;
01082 struct anp {
01083 uint16_t fpc;
01084 uint16_t pic;
01085 in_addr_t address;
01086 uint16_t port;
01087 } key;
01088
01089
01090 mon = mon_entry(patricia_get(&monitors_conf, strlen(name) + 1, name));
01091
01092 if(mon == NULL) {
01093 LOG(TRACE_LOG_WARNING, "%s: statistic received for a flow in a monitor "
01094 "that is not configured (ignored)", __func__);
01095 return;
01096 }
01097
01098
01099
01100 key.fpc = fpc_slot;
01101 key.pic = pic_slot;
01102 key.address = flow_addr;
01103 key.port = flow_port;
01104
01105 fs = fs_entry(patricia_get(mon->flow_stats, sizeof(in_addr_t) +
01106 (3 * sizeof(uint16_t)), &key));
01107
01108 if(fs == NULL) {
01109 fs = calloc(1, sizeof(flowstat_t));
01110 INSIST(fs != NULL);
01111 fs->fpc_slot = fpc_slot;
01112 fs->pic_slot = pic_slot;
01113 fs->flow_addr = flow_addr;
01114 fs->flow_port = flow_port;
01115 fs->mon = mon;
01116
01117 if(!patricia_add(mon->flow_stats, &fs->node)) {
01118 LOG(TRACE_LOG_ERR, "%s: Failed to add a flow stat to configuration",
01119 __func__);
01120 free(fs);
01121 return;
01122 }
01123
01124 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s: Added a new flow statistic "
01125 "for monitor %s", __func__, name);
01126
01127 } else {
01128 if(evTestID(fs->timer_id)) {
01129 evClearTimer(m_ctx, fs->timer_id);
01130 }
01131 }
01132
01133 fs->last_mdi_df[fs->window_position] = mdi_df;
01134 fs->last_mdi_mlr[fs->window_position] = mdi_mlr;
01135 fs->reports++;
01136 fs->window_position++;
01137 if(fs->window_position == STATS_BASE_WINDOW) {
01138 fs->window_position = 0;
01139 }
01140
01141
01142
01143 if(evSetTimer(m_ctx, age_out_flow_stat, fs,
01144 evAddTime(evNowTime(), evConsTime(MAX_FLOW_AGE, 0)),
01145 evConsTime(0, 0), &fs->timer_id)) {
01146
01147 LOG(LOG_EMERG, "%s: evSetTimer() failed! Will not be "
01148 "able to age out flow statistics", __func__);
01149 }
01150 }
01151
01152
01156 void
01157 clear_all_flowstats(void)
01158 {
01159 monitor_t * mon;
01160
01161 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
01162
01163 mon = next_monitor(NULL);
01164 while(mon != NULL) {
01165
01166 delete_all_flowstats(mon);
01167
01168 mon = next_monitor(mon);
01169 }
01170 }
01171
01172
01182 int
01183 clear_flowstats(char * mon_name)
01184 {
01185 monitor_t * mon;
01186
01187 junos_trace(MONITUBE_TRACEFLAG_CONF, "%s", __func__);
01188
01189
01190 mon = mon_entry(patricia_get(&monitors_conf, strlen(mon_name)+1, mon_name));
01191
01192 if(mon == NULL) {
01193 return -1;
01194 }
01195
01196 delete_all_flowstats(mon);
01197 return 0;
01198 }