/* * builtin-record.c * * Builtin record command: Record the profile of a workload * (or a CPU, or a PID) into the perf.data output file - for * later analysis via perf report. */ #include "builtin.h" #include "perf.h" #include "util/build-id.h" #include "util/util.h" #include "util/parse-options.h" #include "util/parse-events.h" #include "util/callchain.h" #include "util/cgroup.h" #include "util/header.h" #include "util/event.h" #include "util/evlist.h" #include "util/evsel.h" #include "util/debug.h" #include "util/session.h" #include "util/tool.h" #include "util/symbol.h" #include "util/cpumap.h" #include "util/thread_map.h" #include "util/data.h" #include "util/perf_regs.h" #include "util/auxtrace.h" #include "util/parse-branch-options.h" #include "util/parse-regs-options.h" #include "util/llvm-utils.h" #include <unistd.h> #include <sched.h> #include <sys/mman.h> struct record { struct perf_tool tool; struct record_opts opts; u64 bytes_written; struct perf_data_file file; struct auxtrace_record *itr; struct perf_evlist *evlist; struct perf_session *session; const char *progname; int realtime_prio; bool no_buildid; bool no_buildid_cache; unsigned long long samples; }; static int record__write(struct record *rec, void *bf, size_t size) { if (perf_data_file__write(rec->session->file, bf, size) < 0) { pr_err("failed to write perf data, error: %m\n"); return -1; } rec->bytes_written += size; return 0; } static int process_synthesized_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { struct record *rec = container_of(tool, struct record, tool); return record__write(rec, event, event->header.size); } static int record__mmap_read(struct record *rec, int idx) { struct perf_mmap *md = &rec->evlist->mmap[idx]; u64 head = perf_mmap__read_head(md); u64 old = md->prev; unsigned char *data = md->base + page_size; unsigned long size; void *buf; int rc = 0; if (old == head) return 0; rec->samples++; size = head - old; if ((old & md->mask) + size != (head & md->mask)) { buf = &data[old & md->mask]; size = md->mask + 1 - (old & md->mask); old += size; if (record__write(rec, buf, size) < 0) { rc = -1; goto out; } } buf = &data[old & md->mask]; size = head - old; old += size; if (record__write(rec, buf, size) < 0) { rc = -1; goto out; } md->prev = old; perf_evlist__mmap_consume(rec->evlist, idx); out: return rc; } static volatile int done; static volatile int signr = -1; static volatile int child_finished; static volatile int auxtrace_snapshot_enabled; static volatile int auxtrace_snapshot_err; static volatile int auxtrace_record__snapshot_started; static void sig_handler(int sig) { if (sig == SIGCHLD) child_finished = 1; else signr = sig; done = 1; } static void record__sig_exit(void) { if (signr == -1) return; signal(signr, SIG_DFL); raise(signr); } #ifdef HAVE_AUXTRACE_SUPPORT static int record__process_auxtrace(struct perf_tool *tool, union perf_event *event, void *data1, size_t len1, void *data2, size_t len2) { struct record *rec = container_of(tool, struct record, tool); struct perf_data_file *file = &rec->file; size_t padding; u8 pad[8] = {0}; if (!perf_data_file__is_pipe(file)) { off_t file_offset; int fd = perf_data_file__fd(file); int err; file_offset = lseek(fd, 0, SEEK_CUR); if (file_offset == -1) return -1; err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, event, file_offset); if (err) return err; } /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ padding = (len1 + len2) & 7; if (padding) padding = 8 - padding; record__write(rec, event, event->header.size); record__write(rec, data1, len1); if (len2) record__write(rec, data2, len2); record__write(rec, &pad, padding); return 0; } static int record__auxtrace_mmap_read(struct record *rec, struct auxtrace_mmap *mm) { int ret; ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, record__process_auxtrace); if (ret < 0) return ret; if (ret) rec->samples++; return 0; } static int record__auxtrace_mmap_read_snapshot(struct record *rec, struct auxtrace_mmap *mm) { int ret; ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, record__process_auxtrace, rec->opts.auxtrace_snapshot_size); if (ret < 0) return ret; if (ret) rec->samples++; return 0; } static int record__auxtrace_read_snapshot_all(struct record *rec) { int i; int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; if (!mm->base) continue; if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { rc = -1; goto out; } } out: return rc; } static void record__read_auxtrace_snapshot(struct record *rec) { pr_debug("Recording AUX area tracing snapshot\n"); if (record__auxtrace_read_snapshot_all(rec) < 0) { auxtrace_snapshot_err = -1; } else { auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); if (!auxtrace_snapshot_err) auxtrace_snapshot_enabled = 1; } } #else static inline int record__auxtrace_mmap_read(struct record *rec __maybe_unused, struct auxtrace_mmap *mm __maybe_unused) { return 0; } static inline void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) { } static inline int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) { return 0; } #endif static int record__open(struct record *rec) { char msg[512]; struct perf_evsel *pos; struct perf_evlist *evlist = rec->evlist; struct perf_session *session = rec->session; struct record_opts *opts = &rec->opts; int rc = 0; perf_evlist__config(evlist, opts); evlist__for_each(evlist, pos) { try_again: if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { if (verbose) ui__warning("%s\n", msg); goto try_again; } rc = -errno; perf_evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg)); ui__error("%s\n", msg); goto out; } } if (perf_evlist__apply_filters(evlist, &pos)) { error("failed to set filter \"%s\" on event %s with %d (%s)\n", pos->filter, perf_evsel__name(pos), errno, strerror_r(errno, msg, sizeof(msg))); rc = -1; goto out; } if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, opts->auxtrace_mmap_pages, opts->auxtrace_snapshot_mode) < 0) { if (errno == EPERM) { pr_err("Permission error mapping pages.\n" "Consider increasing " "/proc/sys/kernel/perf_event_mlock_kb,\n" "or try again with a smaller value of -m/--mmap_pages.\n" "(current value: %u,%u)\n", opts->mmap_pages, opts->auxtrace_mmap_pages); rc = -errno; } else { pr_err("failed to mmap with %d (%s)\n", errno, strerror_r(errno, msg, sizeof(msg))); rc = -errno; } goto out; } session->evlist = evlist; perf_session__set_id_hdr_size(session); out: return rc; } static int process_sample_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine) { struct record *rec = container_of(tool, struct record, tool); rec->samples++; return build_id__mark_dso_hit(tool, event, sample, evsel, machine); } static int process_buildids(struct record *rec) { struct perf_data_file *file = &rec->file; struct perf_session *session = rec->session; if (file->size == 0) return 0; /* * During this process, it'll load kernel map and replace the * dso->long_name to a real pathname it found. In this case * we prefer the vmlinux path like * /lib/modules/3.16.4/build/vmlinux * * rather than build-id path (in debug directory). * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 */ symbol_conf.ignore_vmlinux_buildid = true; return perf_session__process_events(session); } static void perf_event__synthesize_guest_os(struct machine *machine, void *data) { int err; struct perf_tool *tool = data; /* *As for guest kernel when processing subcommand record&report, *we arrange module mmap prior to guest kernel mmap and trigger *a preload dso because default guest module symbols are loaded *from guest kallsyms instead of /lib/modules/XXX/XXX. This *method is used to avoid symbol missing when the first addr is *in module instead of in guest kernel. */ err = perf_event__synthesize_modules(tool, process_synthesized_event, machine); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" " relocation symbol.\n", machine->pid); /* * We use _stext for guest kernel because guest kernel's /proc/kallsyms * have no _text sometimes. */ err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, machine); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" " relocation symbol.\n", machine->pid); } static struct perf_event_header finished_round_event = { .size = sizeof(struct perf_event_header), .type = PERF_RECORD_FINISHED_ROUND, }; static int record__mmap_read_all(struct record *rec) { u64 bytes_written = rec->bytes_written; int i; int rc = 0; for (i = 0; i < rec->evlist->nr_mmaps; i++) { struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; if (rec->evlist->mmap[i].base) { if (record__mmap_read(rec, i) != 0) { rc = -1; goto out; } } if (mm->base && !rec->opts.auxtrace_snapshot_mode && record__auxtrace_mmap_read(rec, mm) != 0) { rc = -1; goto out; } } /* * Mark the round finished in case we wrote * at least one event. */ if (bytes_written != rec->bytes_written) rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); out: return rc; } static void record__init_features(struct record *rec) { struct perf_session *session = rec->session; int feat; for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) perf_header__set_feat(&session->header, feat); if (rec->no_buildid) perf_header__clear_feat(&session->header, HEADER_BUILD_ID); if (!have_tracepoints(&rec->evlist->entries)) perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); if (!rec->opts.branch_stack) perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); if (!rec->opts.full_auxtrace) perf_header__clear_feat(&session->header, HEADER_AUXTRACE); } static volatile int workload_exec_errno; /* * perf_evlist__prepare_workload will send a SIGUSR1 * if the fork fails, since we asked by setting its * want_signal to true. */ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, void *ucontext __maybe_unused) { workload_exec_errno = info->si_value.sival_int; done = 1; child_finished = 1; } static void snapshot_sig_handler(int sig); static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; int status = 0; unsigned long waking = 0; const bool forks = argc > 0; struct machine *machine; struct perf_tool *tool = &rec->tool; struct record_opts *opts = &rec->opts; struct perf_data_file *file = &rec->file; struct perf_session *session; bool disabled = false, draining = false; int fd; rec->progname = argv[0]; atexit(record__sig_exit); signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); if (rec->opts.auxtrace_snapshot_mode) signal(SIGUSR2, snapshot_sig_handler); else signal(SIGUSR2, SIG_IGN); session = perf_session__new(file, false, tool); if (session == NULL) { pr_err("Perf session creation failed.\n"); return -1; } fd = perf_data_file__fd(file); rec->session = session; record__init_features(rec); if (forks) { err = perf_evlist__prepare_workload(rec->evlist, &opts->target, argv, file->is_pipe, workload_exec_failed_signal); if (err < 0) { pr_err("Couldn't run the workload!\n"); status = err; goto out_delete_session; } } if (record__open(rec) != 0) { err = -1; goto out_child; } /* * Normally perf_session__new would do this, but it doesn't have the * evlist. */ if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { pr_warning("WARNIN<style>.highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span><span class="c1"># Copyright (c) 2016-2017 Intel Corporation</span> <span class="c1">#</span> <span class="c1"># Licensed under the Apache License, Version 2.0 (the "License");</span> <span class="c1"># you may not use this file except in compliance with the License.</span> <span class="c1"># You may obtain a copy of the License at</span> <span class="c1">#</span> <span class="c1"># http://www.apache.org/licenses/LICENSE-2.0</span> <span class="c1">#</span> <span class="c1"># Unless required by applicable law or agreed to in writing, software</span> <span class="c1"># distributed under the License is distributed on an "AS IS" BASIS,</span> <span class="c1"># WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span> <span class="c1"># See the License for the specific language governing permissions and</span> <span class="c1"># limitations under the License.</span> <span class="c1"># flow definition for ACL tests - 1K flows - ipv4 only</span> <span class="c1">#</span> <span class="c1"># the number of flows defines the widest range of parameters</span> <span class="c1"># for example if srcip_range=1.0.0.1-1.0.0.255 and dst_ip_range=10.0.0.1-10.0.1.255</span> <span class="c1"># and it should define only 16 flows</span> <span class="c1">#</span> <span class="c1"># there is assumption that packets generated will have a random sequences of following addresses pairs</span> <span class="c1"># in the packets</span> <span class="c1"># 1. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)</span> <span class="c1"># 2. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)</span> <span class="c1"># ...</span> <span class="c1"># 512. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)</span> <span class="c1">#</span> <span class="c1"># not all combination should be filled</span> <span class="c1"># Any other field with random range will be added to flow definition</span> <span class="c1">#</span> <span class="c1"># the example.yaml provides all possibilities for traffic generation</span> <span class="c1">#</span> <span class="c1"># the profile defines a public and private side to make limited traffic correlation</span> <span class="c1"># between private and public side same way as it is made by IXIA solution.</span> <span class="c1">#</span> <span class="nn">---</span> <span class="l l-Scalar l-Scalar-Plain">schema</span><span class="p p-Indicator">:</span> <span class="s">"nsb:traffic_profile:0.1"</span> <span class="c1"># This file is a template, it will be filled with values from tc.yaml before passing to the traffic generator</span> <span class="l l-Scalar l-Scalar-Plain">name</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">rfc2544</span> <span class="l l-Scalar l-Scalar-Plain">description</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">Traffic profile to run RFC2544 latency</span> <span class="l l-Scalar l-Scalar-Plain">traffic_profile</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">traffic_type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">RFC2544Profile</span> <span class="c1"># defines traffic behavior - constant or look for highest possible throughput</span> <span class="l l-Scalar l-Scalar-Plain">frame_rate</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">100</span> <span class="c1"># pc of linerate</span> <span class="c1"># that specifies a range (e.g. ipv4 address, port)</span> <span class="l l-Scalar l-Scalar-Plain">uplink_0</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">ipv4</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">outer_l2</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">framesize</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">64B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.64B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">128B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.128B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">256B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.256B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">373b</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.373B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">512B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.512B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">570B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.570B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">1400B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.1400B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">1500B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.1500B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">1518B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.uplink.1518B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">outer_l3v4</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">proto</span><span class="p p-Indicator">:</span> <span class="s">"udp"</span> <span class="l l-Scalar l-Scalar-Plain">srcip4</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.src_ip_0',</span><span class="nv"> </span><span class="s">'1.1.1.1-1.1.255.255')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">dstip4</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.dst_ip_0',</span><span class="nv"> </span><span class="s">'90.90.1.1-90.90.255.255')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">count</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.count',</span><span class="nv"> </span><span class="s">'1')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">ttl</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">32</span> <span class="l l-Scalar l-Scalar-Plain">dscp</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">0</span> <span class="l l-Scalar l-Scalar-Plain">outer_l4</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">srcport</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.src_port_0',</span><span class="nv"> </span><span class="s">'1234-4321')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">dstport</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.dst_port_0',</span><span class="nv"> </span><span class="s">'2001')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">count</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.count',</span><span class="nv"> </span><span class="s">'1')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">downlink_0</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">ipv4</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">outer_l2</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">framesize</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">64B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.64B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">128B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.128B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">256B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.256B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">373b</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.373B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">512B</span><span class="p p-Indicator">:</span> <span class="s">"{{</span><span class="nv"> </span><span class="s">get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.512B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">570B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.570B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">1400B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.1400B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">1500B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.1500B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">1518B</span><span class="p p-Indicator">:</span> <span class="s">"{{get(imix,</span><span class="nv"> </span><span class="s">'imix.downlink.1518B',</span><span class="nv"> </span><span class="s">'0')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">outer_l3v4</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">proto</span><span class="p p-Indicator">:</span> <span class="s">"udp"</span> <span class="l l-Scalar l-Scalar-Plain">srcip4</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.dst_ip_0',</span><span class="nv"> </span><span class="s">'10.0.3.1-10.0.3.255')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">dstip4</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.downlink_0',</span><span class="nv"> </span><span class="s">'10.0.2.1-10.0.2.255')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">count</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.count',</span><span class="nv"> </span><span class="s">'1')</span><span class="nv"> </span><span class="s">}}"</span> <span class="l l-Scalar l-Scalar-Plain">ttl</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">32</span> <span class="l l-Scalar l-Scalar-Plain">dscp</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">0</span> <span class="l l-Scalar l-Scalar-Plain">outer_l4</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">srcport</span><span class="p p-Indicator">:</span> <span class="s">"{{get(flow,</span><span class="nv"> </span><span class="s">'flow.dst_port_0',</span><span class="nv"> </span><span class="s">'1234-4321')</span><span class="n