/* *------------------------------------------------------------------ * Copyright (c) 2006-2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cpel.h" #include char *time_format = "%.03d:%.02d:%.02d:%.03d:%.03d "; static char version[] = "cpelatency 2.0"; #define USEC_PER_MS 1000LL #define USEC_PER_SECOND (1000*USEC_PER_MS) #define USEC_PER_MINUTE (60*USEC_PER_SECOND) #define USEC_PER_HOUR (60*USEC_PER_MINUTE) uword *the_strtab_hash; /* (name, base-VA) hash of all string tables */ uword *the_evtdef_hash; /* (event-id, event-definition) hash */ uword *the_trackdef_hash; /* (track-id, track-definition) hash */ uword *the_pidtid_hash; /* ("pid:xxx tid:yy", track-definition) hash */ f64 ticks_per_us; u32 start_event_code = 2; /* default: XR thread ready event */ u32 end_event_code = 1; /* default: XR thread running event */ int exclude_kernel_from_summary_stats=1; int summary_stats_only; int scatterplot; u8 *name_filter; int have_trackdefs; typedef enum { SORT_MAX_TIME=1, SORT_MAX_OCCURRENCES, SORT_NAME, } sort_t; sort_t sort_type = SORT_MAX_TIME; int widest_name_format=5; int widest_track_format=20; typedef struct bound_event_ { u32 event_code; u8 *event_str; u8 *datum_str; u32 is_strtab_ref; } bound_event_t; bound_event_t *bound_events; typedef struct bound_track_ { u32 track; u8 *track_str; u64 state_start_ticks; u64 *ticks_in_state; /* vector of state occurrences */ f64 mean_ticks_in_state; f64 variance_ticks_in_state; f64 total_ticks_in_state; } bound_track_t; bound_track_t *bound_tracks; void fatal(char *s) { fprintf(stderr, "%s", s); exit(1); } typedef enum { PASS1=1, PASS2=2, } pass_t; typedef struct { int (*pass1)(cpel_section_header_t *, int, FILE *); int (*pass2)(cpel_section_header_t *, int, FILE *); } section_processor_t; int bad_section(cpel_section_header_t *sh, int verbose, FILE *ofp) { fprintf(ofp, "Bad (type 0) section, skipped...\n"); return(0); } int noop_pass(cpel_section_header_t *sh, int verbose, FILE *ofp) { return(0); } int strtab_pass1(cpel_section_header_t *sh, int verbose, FILE *ofp) { uword *p; u8 *strtab_data_area = (u8 *)(sh+1); /* Multiple string tables with the same name are Bad... */ p = hash_get_mem(the_strtab_hash, strtab_data_area); if (p) { fprintf(ofp, "Duplicate string table name %s", strtab_data_area); } /* * Looks funny, but we really do want key = first string in the * table, value = address(first string in the table) */ hash_set_mem(the_strtab_hash, strtab_data_area, strtab_data_area); if (verbose) { fprintf(ofp, "String Table %s\n", strtab_data_area); } return(0); } int evtdef_pass1(cpel_section_header_t *sh, int verbose, FILE *ofp) { int i, nevents; event_definition_section_header_t *edh; event_definition_t *ep; u8 *this_strtab; u32 event_code; uword *p; bound_event_t *bp; int thislen; edh = (event_definition_section_header_t *)(sh+1); nevents = ntohl(edh->number_of_event_definitions); if (verbose) { fprintf(ofp, "Event Definition Section: %d definitions\n", nevents); } p = hash_get_mem(the_strtab_hash, edh->string_table_name); if (!p) { fprintf(ofp, "Fatal: couldn't find string table\n"); return(1); } this_strtab = (u8 *)p[0]; ep = (event_definition_t *)(edh+1); for (i = 0; i < nevents; i++) { event_code = ntohl(ep->event); p = hash_get(the_evtdef_hash, event_code); if (p) { fprintf(ofp, "Event %d redefined, retain first definition\n", event_code); continue; } vec_add2(bound_events, bp, 1); bp->event_code = event_code; bp->event_str = this_strtab + ntohl(ep->event_format); bp->datum_str = this_strtab + ntohl(ep->datum_format); bp->is_strtab_ref = 0; /* Decide if the datum format is a %s format => strtab reference */ { int j; int seen_percent=0; for (j = 0; j < strlen((char *) bp->datum_str); j++) { if (bp->datum_str[j] == '%'){ seen_percent=1; continue; } if (seen_percent && bp->datum_str[j] == 's') { bp->is_strtab_ref = 1; } } } hash_set(the_evtdef_hash, event_code, bp - bound_events); thislen = strlen((char *) bp->event_str); if (thislen > widest_name_format) widest_name_format = thislen; ep++; } return (0); } int trackdef_pass1(cpel_section_header_t *sh, int verbose, FILE *ofp) { int i, nevents; track_definition_section_header_t *tdh; track_definition_t *tp; u8 *this_strtab; u32 track_code; uword *p; bound_track_t *btp; int thislen; u8 *pidstr; u8 *pidtid_str; u8 *cp; int tid, pid; tdh = (track_definition_section_header_t *)(sh+1); nevents = ntohl(tdh->number_of_track_definitions); if (verbose) { fprintf(ofp, "Track Definition Section: %d definitions\n", nevents); } p = hash_get_mem(the_strtab_hash, tdh->string_table_name); if (!p) { fprintf(ofp, "Fa
# Copyright (c) 2016 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Constants used in CSIT."""


class Constants(object):
    """Constants used in CSIT."""

    # OpenVPP testing directory location at topology nodes
    REMOTE_FW_DIR = "/tmp/openvpp-testing"

    # shell scripts location
    RESOURCES_LIB_SH = "resources/libraries/bash"

    # vat templates location
    RESOURCES_TPL_VAT = "resources/templates/vat"

    # OpenVPP VAT binary name
    VAT_BIN_NAME = "vpp_api_test"

    # QEMU version to install
    QEMU_INSTALL_VERSION = "qemu-2.5.0"

    # QEMU install directory
    QEMU_INSTALL_DIR = "/opt/qemu-2.5.0"

    # Honeycomb directory location at topology nodes:
    REMOTE_HC_DIR = "/opt/honeycomb"

    # Honeycomb persistence files location
    REMOTE_HC_PERSIST = "/var/lib/honeycomb/persist"

    # Honeycomb templates location
    RESOURCES_TPL_HC = "resources/templates/honeycomb"

    # ODL Client Restconf listener port
    ODL_PORT = 8181
*)name_filter))) continue; /* * Exclude kernel threads (e.g. idle thread) from * state statistics */ if (exclude_kernel_from_summary_stats && !strncmp((char *) bp->track_str, "kernel ", 7)) continue; total_switches += (f64) vec_len(bp->ticks_in_state); if (!summary_stats_only) { fprintf(ofp, (char *) trackpad, bp->track_str); fprintf(ofp, "%10.3f +- %10.3f", bp->mean_ticks_in_state / ticks_per_us, sqrt(bp->variance_ticks_in_state) / ticks_per_us); fprintf(ofp, "%12.3f", bp->total_ticks_in_state / ticks_per_us); fprintf(ofp, "%8d\n", vec_len(bp->ticks_in_state)); } if (scatterplot) { for (j = 0; j < vec_len(bp->ticks_in_state); j++) { fprintf(ofp, "%.3f\n", (f64)bp->ticks_in_state[j] / ticks_per_us); } } total_time += bp->total_ticks_in_state; } if (!summary_stats_only) fprintf(ofp, "\n"); fprintf(ofp, "Note: the following statistics %s kernel-thread activity.\n", exclude_kernel_from_summary_stats ? "exclude" : "include"); if (name_filter) fprintf(ofp, "Note: only pid/proc/threads matching '%s' are included.\n", name_filter); fprintf(ofp, "Total time in state: %10.3f (us), Total state occurrences: %.0f\n", total_time / ticks_per_us, total_switches); fprintf(ofp, "Average time in state: %10.3f (us)\n", (total_time / total_switches) / ticks_per_us); fprintf(ofp, "State start event: %d, state end event: %d\n", start_event_code, end_event_code); } char *mapfile (char *file) { struct stat statb; char *rv; int maphfile; size_t mapfsize; maphfile = open (file, O_RDONLY); if (maphfile < 0) { fprintf (stderr, "Couldn't read %s, skipping it...\n", file); return (NULL); } if (fstat (maphfile, &statb) < 0) { fprintf (stderr, "Couldn't get size of %s, skipping it...\n", file); return (NULL); } /* Don't try to mmap directories, FIFOs, semaphores, etc. */ if (! (statb.st_mode & S_IFREG)) { fprintf (stderr, "%s is not a regular file, skipping it...\n", file); return (NULL); } mapfsize = statb.st_size; if (mapfsize < 3) { fprintf (stderr, "%s zero-length, skipping it...\n", file); close (maphfile); return (NULL); } rv = mmap (0, mapfsize, PROT_READ, MAP_SHARED, maphfile, 0); if (rv == 0) { fprintf (stderr, "%s problem mapping, I quit...\n", file); exit (-1); } close (maphfile); return (rv); } /* * main */ int main (int argc, char **argv) { char *cpel_file = 0; char *outputfile = 0; FILE *ofp; char *cpel; int verbose=0; int curarg=1; while (curarg < argc) { if (!strncmp(argv[curarg], "--input-file", 3)) { curarg++; if (curarg < argc) { cpel_file = argv[curarg]; curarg++; continue; } fatal("Missing filename after --input-file\n"); } if (!strncmp(argv[curarg], "--output-file", 3)) { curarg ++; if (curarg < argc) { outputfile = argv[curarg]; curarg ++; continue; } fatal("Missing filename after --output-file\n"); } if (!strncmp(argv[curarg], "--verbose", 3)) { curarg++; verbose++; continue; } if (!strncmp(argv[curarg], "--scatterplot", 4)) { curarg++; scatterplot=1; continue; } if (!strncmp(argv[curarg], "--start-event", 4)) { curarg++; if (curarg < argc) { start_event_code = atol(argv[curarg]); curarg ++; continue; } fatal("Missing integer after --start-event\n"); } if (!strncmp(argv[curarg], "--end-event", 4)) { curarg++; if (curarg < argc) { end_event_code = atol(argv[curarg]); curarg ++; continue; } fatal("Missing integer after --end-event\n"); } if (!strncmp(argv[curarg], "--max-time-sort", 7)) { sort_type = SORT_MAX_TIME; curarg++; continue; } if (!strncmp(argv[curarg], "--max-occurrence-sort", 7)) { sort_type = SORT_MAX_OCCURRENCES; curarg++; continue; } if (!strncmp(argv[curarg], "--name-sort", 3)) { sort_type = SORT_NAME; curarg++; continue; } if (!strncmp(argv[curarg], "--kernel-included", 3)) { exclude_kernel_from_summary_stats = 0; curarg++; continue; } if (!strncmp(argv[curarg], "--summary", 3)) { summary_stats_only=1; curarg++; continue; } if (!strncmp(argv[curarg], "--filter", 3)) { curarg ++; if (curarg < argc) { name_filter = (u8 *) argv[curarg]; curarg ++; continue; } fatal("Missing filter string after --filter\n"); } usage: fprintf(stderr, "cpelatency --input-file [--output-file ]\n"); fprintf(stderr, " [--start-event ] [--verbose]\n"); fprintf(stderr, " [--end-event ]\n"); fprintf(stderr, " [--max-time-sort(default) | --max-occurrence-sort |\n"); fprintf(stderr, " --name-sort-sort] [--kernel-included]\n"); fprintf(stderr, " [--summary-stats-only] [--scatterplot]\n"); fprintf(stderr, "%s\n", version); exit(1); } if (cpel_file == 0) goto usage; cpel = mapfile(cpel_file); if (cpel == 0) { fprintf(stderr, "Couldn't map %s...\n", cpel_file); exit(1); } if (!outputfile) { ofp = fdopen(1, "w"); if (ofp == NULL) { fprintf(stderr, "Couldn't fdopen(1)?\n"); exit(1); } } else { ofp = fopen(outputfile, "w"); if (ofp == NULL) { fprintf(stderr, "Couldn't create %s...\n", outputfile); exit(1); } } the_strtab_hash = hash_create_string (0, sizeof (uword)); the_evtdef_hash = hash_create (0, sizeof (uword)); the_trackdef_hash = hash_create (0, sizeof (uword)); the_pidtid_hash = hash_create_string (0, sizeof(uword)); if (cpel_dump((u8 *)cpel, verbose, ofp)) { if (outputfile) unlink(outputfile); } compute_state_statistics(verbose, ofp); sort_state_statistics(sort_type, ofp); print_state_statistics(verbose, ofp); fclose(ofp); return(0); }