/* * $Id: ospf_anal.c,v 2.2 2000/05/23 08:06:24 masaki Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sospf.h" #include "ospf_anal.h" /* * GLOBALS */ trace_t *default_trace; ospf_t OSPF; static io_t *IO; ospf_stats_t OSPF_STATS; int TIME_ASCII = 0; /* local functions */ static void process_input (); static time_t calc_start_time (char *date); int compare_links (int n, ospf_router_link_t *link1, ospf_router_link_t *link2); void count_lsa (char *header, int num_lsa); void ospf_stat_router_lsa (ospf_router_lsa_t *lsa); void ospf_stat_network_lsa (ospf_network_lsa_t *lsa); void ospf_stat_external_lsa (ospf_external_lsa_t *lsa); void report (); void main (int argc, char *argv[]) { char c; extern char *optarg; /* getopt stuff */ extern int optind; /* getopt stuff */ int file_flag = 0; int errors = 0; char *usage = "Usage: ospf_anal [-v] [-i] [-t] [-f file]\n"; IO = New_IO (default_trace); io_set (IO, IO_INFILE, "stdin", NULL); default_trace = New_Trace (); init_ospf (); OSPF_STATS.ll_router_lsa = LL_Create (0); OSPF_STATS.ll_network_lsa = LL_Create (0); OSPF_STATS.ll_external_lsa = LL_Create (0); while ((c = getopt (argc, argv, "vmhf:id:t")) != -1) switch (c) { case 'v': /* verbose */ set_trace (default_trace, TRACE_FLAGS, TR_PACKET | NORM, TRACE_LOGFILE, "stdout", NULL); break; case 'i': case 'f': file_flag = 1; break; case 'd': OSPF_STATS.start_time = calc_start_time (optarg); break; case 't': TIME_ASCII = 1; break; case 'm': OSPF_STATS.machine_readable = 1; break; case 'h': default: errors++; break; } if (errors) { fprintf (stderr, usage); printf ("\nMRT version (%s) compiled on %s\n\n", MRT_VERSION, __DATE__); printf ("Report format:\n"); printf (" TIME|NLSA|Advr Router|Link Id|Network Mask|[Routers|]...\n"); printf (" TIME|RLSA|Advr Router|Link Id|[linktype|link_id]...\n"); exit (0); } init_mrt (default_trace); init_uii (default_trace); init_interfaces (default_trace); /* set up calback functions */ OSPF.ospf_lsa_call_fn = count_lsa; OSPF.ospf_router_lsa_call_fn = ospf_stat_router_lsa; OSPF.ospf_network_lsa_call_fn = ospf_stat_network_lsa; OSPF.ospf_external_lsa_call_fn = ospf_stat_external_lsa; /* user commands */ uii_add_command2 (UII_NORMAL, COMMAND_NORM, "config", (void *) start_config, "Configure sospf"); uii_add_command2 (UII_NORMAL, COMMAND_NORM, "write", (void *) config_write, "Save configuration to disk"); uii_add_command2 (UII_NORMAL, COMMAND_NORM, "show config", show_config, "Display current configuration"); uii_add_command2 (UII_NORMAL, COMMAND_NORM, "show ip ospf neighbors", (void *) show_ospf_neighbors, "Show status of OSPF nieghbors"); uii_add_command2 (UII_NORMAL, COMMAND_NORM, "show ip ospf database", (void *) show_ospf_database, "Database summary"); if (file_flag) { for ( ; optind < argc; optind++) { if (io_set (IO, IO_INFILE, (char *) argv[optind], NULL) < 0) { printf ("Failed to open infile %s", (char *) optarg); exit (0); } /*printf ("%s\n", argv[optind]);*/ process_input (); } } if (OSPF_STATS.start_time > 0) { int i; for (i=0; i< 1440; i++) { printf ("%d %d\n", i, OSPF_STATS.time_buckets[i]); } } /*report ();*/ } /* void report () { char tmp1[MAXLINE], tmp2[MAXLINE]; ospf_router_lsa_stats_t *router_lsa; ospf_network_lsa_stats_t *network_lsa; LL_Iterate (OSPF_STATS.ll_router_lsa, router_lsa) { printf ("%s [changes %d]\n", long_inet_ntoa (router_lsa->router_id), router_lsa->num_changes); } LL_Iterate (OSPF_STATS.ll_network_lsa, network_lsa) { sprintf (tmp1, "%s", long_inet_ntoa (network_lsa->network_mask)); sprintf (tmp2, "%s", long_inet_ntoa (network_lsa->link_state_id)); printf ("%d NLSA %s (link id: %s) network %s [changes %d]\n", long_inet_ntoa (network_lsa->adver_router), tmp2, tmp1, network_lsa->num_changes); } } */ void process_input () { static ospf_header_t ospf_header; mrt_msg_t *msg; int i; while (1) { if ((msg = (mrt_msg_t *) io_read (IO)) == NULL) { return; } /*printf ("Msg %d %d\n", msg->length, msg->tstamp);*/ if (msg->type == MSG_PROTOCOL_OSPF) { OSPF_STATS.time = msg->tstamp; if (ospf_process_header (&ospf_header, msg->value)) { /*printf ("Error %d\n", msg->length); if (i++ > 400) {exit (0);}*/ } } Delete (msg); } } void count_lsa (char *header, int num_lsa) { u_long bucket; if (OSPF_STATS.start_time > 0) { bucket = (OSPF_STATS.time - OSPF_STATS.start_time) / (60); OSPF_STATS.time_buckets[bucket] += num_lsa; } } static time_t calc_start_time (char *date) { int y,m,d; struct tm timeptr; u_long l; sscanf (date, "%2d%2d%2d", &y, &m, &d); memset (&timeptr, 0, sizeof (struct tm)); timeptr.tm_mday = d; timeptr.tm_mon = m -1; timeptr.tm_year = y; l = mktime (&timeptr); return (l); } void ospf_stat_router_lsa (ospf_router_lsa_t *lsa) { ospf_router_lsa_stats_t *tmp_lsa; ospf_router_link_t *link1, *link2; char tmp1[MAXLINE]; int i, found = 0; u_long last; /*printf ("%s\n", long_inet_ntoa (lsa->header->id));*/ LL_Iterate (OSPF_STATS.ll_router_lsa, tmp_lsa) { if (tmp_lsa->router_id == lsa->header->id) { found = 1; break; } } if (!found) { tmp_lsa = New (ospf_router_lsa_stats_t); tmp_lsa->router_id = lsa->header->adv_router; tmp_lsa->num_changes = 0; LL_Add (OSPF_STATS.ll_router_lsa, tmp_lsa); tmp_lsa->last = OSPF_STATS.time; } /* compare the two */ else if ((tmp_lsa->num_links != lsa->num_links) || !compare_links (lsa->num_links, tmp_lsa->ospf_router_links, lsa->links)) { tmp_lsa->num_changes++; Delete (tmp_lsa->ospf_router_links); } else { tmp_lsa->last = OSPF_STATS.time; return; /* exactly the same */ } last = tmp_lsa->last; tmp_lsa->last = OSPF_STATS.time; sprintf (tmp1, "%s", long_inet_ntoa (lsa->header->id)); printf ("%d|RLSA|%d|[%d]|(%d)|%s|%s|", (int) OSPF_STATS.time, lsa->header->age, tmp_lsa->num_changes, tmp_lsa->last - last, long_inet_ntoa (lsa->header->adv_router), tmp1); link2 = (ospf_router_link_t *) lsa->links; for (i=0; i < lsa->num_links; i++) { sprintf (tmp1, "%s", long_inet_ntoa (link2->link_data)); printf ("%d|%s|%d|%s|", link2->type, long_inet_ntoa (link2->link_id), link2->metric, tmp1); link2++; } printf ("\n"); /* copy links */ tmp_lsa->ospf_router_links = NewArray (ospf_router_link_t, lsa->num_links); tmp_lsa->num_links = lsa->num_links; tmp_lsa->last = OSPF_STATS.time; link1 = tmp_lsa->ospf_router_links; link2 = lsa->links; for (i=0; i < lsa->num_links; i++) { link1->type = link2->type; link1->metric = link2->metric; link1->link_id = link2->link_id; link1->link_data = link2->link_data; link1++; link2++; } } int compare_links (int n, ospf_router_link_t *link1, ospf_router_link_t *link2) { ospf_router_link_t *tmp; int i, ii, found; for (i=0; i < n; i++) { found = 0; tmp = link2; for (ii=0; i < n; i++) { if ((link1->type == tmp->type) && (link1->metric == tmp->metric) && (link1->link_id == tmp->link_id) && (link1->link_data == tmp->link_data)) { break; found =1; } tmp++; } if (!found) return (-1); link1++; } return (1); } void ospf_stat_network_lsa (ospf_network_lsa_t *lsa) { ospf_network_lsa_stats_t *network_lsa; char tmp1[MAXLINE], tmp2[MAXLINE], *cp; u_long router; int n, found = 0; u_long last; LL_Iterate (OSPF_STATS.ll_network_lsa, network_lsa) { if (network_lsa->link_state_id == lsa->header->id) { found = 1; break; } } if (!found) { network_lsa = New (ospf_network_lsa_stats_t); LL_Add (OSPF_STATS.ll_network_lsa, network_lsa); network_lsa->last = OSPF_STATS.time; } else if ((network_lsa->num_routers != lsa->num_routers) || ((memcmp (network_lsa->routers, lsa->routers, 4*lsa->num_routers)) != 0)) { network_lsa->num_changes++; Delete (network_lsa->routers); } else { network_lsa->last = OSPF_STATS.time; return; } last = network_lsa->last; network_lsa->last = OSPF_STATS.time; network_lsa->link_state_id = lsa->header->id; network_lsa->network_mask = lsa->network_mask; network_lsa->adver_router = lsa->header->adv_router; network_lsa->num_changes = 0; network_lsa->num_routers = lsa->num_routers; network_lsa->routers = NewArray (u_long, lsa->num_routers); memcpy (network_lsa->routers, lsa->routers, 4*lsa->num_routers); sprintf (tmp1, "%s", long_inet_ntoa (network_lsa->network_mask)); sprintf (tmp2, "%s", long_inet_ntoa (network_lsa->link_state_id)); printf ("%d|NLSA|%d|[%d]|(%d)|%s|%s|%s|",(int) OSPF_STATS.time, lsa->header->age, network_lsa->num_changes, network_lsa->last - last, (char *) long_inet_ntoa (network_lsa->adver_router), tmp2, tmp1); n = lsa->num_routers; cp = (char *) lsa->routers; while (n--) { UTIL_GET_NETLONG (router, cp); printf ("%s|", long_inet_ntoa (router)); } printf ("\n"); } void ospf_stat_external_lsa (ospf_external_lsa_t *lsa) { ospf_external_lsa_stats_t *external_lsa = NULL; char tmp1[MAXLINE], tmp2[MAXLINE]; int found = 0, m; u_long last; LL_Iterate (OSPF_STATS.ll_external_lsa, external_lsa) { if ((external_lsa->link_state_id == lsa->header->id) && (external_lsa->network_mask == lsa->network_mask) && (external_lsa->adver_router == lsa->header->adv_router)) { found = 1; break; } } if (!found) { external_lsa = New (ospf_external_lsa_stats_t); LL_Add (OSPF_STATS.ll_external_lsa, external_lsa); external_lsa->last = OSPF_STATS.time; } else if ((external_lsa->metric != lsa->metric)) { external_lsa->num_changes++; } else { external_lsa->last = OSPF_STATS.time; return; } last = external_lsa->last; external_lsa->last = OSPF_STATS.time; external_lsa->adver_router = lsa->header->adv_router; external_lsa->link_state_id = lsa->header->id; external_lsa->network_mask = lsa->network_mask; m = external_lsa->metric; external_lsa->metric = lsa->metric; if (external_lsa->num_changes > 0) { sprintf (tmp2, "%s", long_inet_ntoa (external_lsa->link_state_id)); sprintf (tmp1, "%s", long_inet_ntoa (lsa->network_mask)); printf ("%d|ELSA|%d|[%d]|(%d)|%s|%s|%s|%d\n", (int) OSPF_STATS.time, lsa->header->age, external_lsa->num_changes, external_lsa->last - last, (char *) long_inet_ntoa (external_lsa->adver_router), tmp2, tmp1, (int) external_lsa->metric); } } .