On 27 Jul 2022, at 16:48, Kevin Sprague wrote:

> During normal operations, it is useful to understand when a particular flow
> gets removed from the system. This can be useful when debugging performance
> issues tied to ofproto flow changes, trying to determine deployed traffic
> patterns, or while debugging dynamic systems where ports come and go.
>
> Prior to this change, there was a lack of visibility around flow expiration.
> The existing debugging infrastructure could tell us when a flow was added to
> the datapath, but not when it was removed or why.
>
> This change introduces a USDT probe at the point where the revalidator
> determines that the flow should be removed.  Additionally, we track the
> reason for the flow eviction and provide that information as well.  With
> this change, we can track the complete flow lifecycle for the netlink datapath
> by hooking the upcall tracepoint in kernel, the flow put USDT, and the
> revaldiator USDT, letting us watch as flows are added and removed from the
> kernel datapath.
>
> This change only enables this information via USDT probe, so it won't be
> possible to access this information any other way (see:
> Documentation/topics/usdt-probes.rst).
>
> Also included is a script (utilities/usdt-scripts/filter_probe.py) that serves
> as a demonstration of how the new USDT probe might be used going forward.
>
> Signed-off-by: Kevin Sprague <kspra...@redhat.com>

See comments below, but it's not a full review, as unfortunately, I was running 
out of time...

//Eelco

> ---
>  Documentation/topics/usdt-probes.rst   |  21 +
>  ofproto/ofproto-dpif-upcall.c          |  40 +-
>  utilities/automake.mk                  |   2 +
>  utilities/usdt-scripts/filter_probe.py | 549 +++++++++++++++++++++++++
>  4 files changed, 606 insertions(+), 6 deletions(-)
>  create mode 100755 utilities/usdt-scripts/filter_probe.py
>
> diff --git a/Documentation/topics/usdt-probes.rst 
> b/Documentation/topics/usdt-probes.rst
> index 7ce19aaed..a977dc006 100644
> --- a/Documentation/topics/usdt-probes.rst
> +++ b/Documentation/topics/usdt-probes.rst
> @@ -214,6 +214,7 @@ Available probes in ``ovs_vswitchd``:
>  - dpif_recv:recv_upcall
>  - main:poll_block
>  - main:run_start
> +- revalidate:flow_result
>
>
>  dpif_netlink_operate\_\_:op_flow_del
> @@ -294,6 +295,7 @@ DPIF_OP_FLOW_PUT operation as part of the dpif 
> ``operate()`` callback.
>
>  **Script references**:
>
> +- ``utilities/usdt-scripts/filter_probe.py``
>  - ``utilities/usdt-scripts/upcall_cost.py``
>
>
> @@ -357,6 +359,25 @@ See also the ``main:run_start`` probe above.
>
>  - ``utilities/usdt-scripts/bridge_loop.bt``

Need extra CR/LF here.
>
> +probe revalidate:flow_result
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +**Description**:
> +This probe is triggered when the revalidator decides whether or not to
> +revalidate a flow. ``reason`` is an enum that denotes that either the flow
> +is being kept, or the reason why the flow is being deleted. The
> +``filter_probe.py`` script uses this probe to notify users when flows
> +matching user-provided criteria are deleted.
> +
> +**Arguments**:
> +
> +- *arg0*: ``(enum flow_del_reason) reason``
> +- *arg1*: ``(struct udpif *) udpif``
> +- *arg2*: ``(struct udpif_key *) ukey``
> +
> +**Script references**:
> +
> +- ``utilities/usdt-scripts/filter_probe.py``
>
>  Adding your own probes
>  ----------------------
> diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
> index 57f94df54..efee8c0a4 100644
> --- a/ofproto/ofproto-dpif-upcall.c
> +++ b/ofproto/ofproto-dpif-upcall.c
> @@ -31,6 +31,7 @@
>  #include "openvswitch/list.h"
>  #include "netlink.h"
>  #include "openvswitch/ofpbuf.h"
> +#include "openvswitch/usdt-probes.h"
>  #include "ofproto-dpif-ipfix.h"
>  #include "ofproto-dpif-sflow.h"
>  #include "ofproto-dpif-xlate.h"
> @@ -260,6 +261,17 @@ enum ukey_state {
>  };
>  #define N_UKEY_STATES (UKEY_DELETED + 1)
>
> +enum flow_del_reason {
> +    FDR_FLOW_LIVE = 0,
> +    FDR_FLOW_TIME_OUT,      /* the flow went unused and was deleted. */

Start with a capital T.

> +    FDR_TOO_EXPENSIVE,
> +    FDR_FLOW_WILDCARDED,
> +    FDR_BAD_ODP_FIT,
> +    FDR_ASSOCIATED_OFPROTO,
> +    FDR_XLATION_ERROR,
> +    FDR_AVOID_CACHING,

I think it would make sense to add a description to each delete reason so that 
when people use the USDT script, they can easily understand why the flow got 
deleted.

> +};
> +
>  /* 'udpif_key's are responsible for tracking the little bit of state udpif
>   * needs to do flow expiration which can't be pulled directly from the
>   * datapath.  They may be created by any handler or revalidator thread at any
> @@ -2202,7 +2214,8 @@ populate_xcache(struct udpif *udpif, struct udpif_key 
> *ukey,
>  static enum reval_result
>  revalidate_ukey__(struct udpif *udpif, const struct udpif_key *ukey,
>                    uint16_t tcp_flags, struct ofpbuf *odp_actions,
> -                  struct recirc_refs *recircs, struct xlate_cache *xcache)
> +                  struct recirc_refs *recircs, struct xlate_cache *xcache,
> +                  enum flow_del_reason *reason)
>  {
>      struct xlate_out *xoutp;
>      struct netflow *netflow;
> @@ -2220,11 +2233,13 @@ revalidate_ukey__(struct udpif *udpif, const struct 
> udpif_key *ukey,
>      netflow = NULL;
>
>      if (xlate_ukey(udpif, ukey, tcp_flags, &ctx)) {
> +        *reason = FDR_XLATION_ERROR;
>          goto exit;
>      }
>      xoutp = &ctx.xout;
>
>      if (xoutp->avoid_caching) {
> +        *reason = FDR_AVOID_CACHING;
>          goto exit;
>      }
>
> @@ -2238,6 +2253,7 @@ revalidate_ukey__(struct udpif *udpif, const struct 
> udpif_key *ukey,
>          ofpbuf_clear(odp_actions);
>
>          if (!ofproto) {
> +            *reason = FDR_ASSOCIATED_OFPROTO;
>              goto exit;
>          }
>
> @@ -2249,6 +2265,7 @@ revalidate_ukey__(struct udpif *udpif, const struct 
> udpif_key *ukey,
>      if (odp_flow_key_to_mask(ukey->mask, ukey->mask_len, &dp_mask, &ctx.flow,
>                               NULL)
>          == ODP_FIT_ERROR) {
> +        *reason = FDR_BAD_ODP_FIT;
>          goto exit;
>      }
>
> @@ -2258,6 +2275,7 @@ revalidate_ukey__(struct udpif *udpif, const struct 
> udpif_key *ukey,
>       * down.  Note that we do not know if the datapath has ignored any of the
>       * wildcarded bits, so we may be overly conservative here. */
>      if (flow_wildcards_has_extra(&dp_mask, ctx.wc)) {
> +        *reason = FDR_FLOW_WILDCARDED;
>          goto exit;
>      }
>
> @@ -2303,7 +2321,8 @@ static enum reval_result
>  revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
>                  const struct dpif_flow_stats *stats,
>                  struct ofpbuf *odp_actions, uint64_t reval_seq,
> -                struct recirc_refs *recircs, bool offloaded)
> +                struct recirc_refs *recircs, bool offloaded,
> +                enum flow_del_reason *reason)
>      OVS_REQUIRES(ukey->mutex)
>  {
>      bool need_revalidate = ukey->reval_seq != reval_seq;
> @@ -2329,8 +2348,12 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key 
> *ukey,
>                  xlate_cache_clear(ukey->xcache);
>              }
>              result = revalidate_ukey__(udpif, ukey, push.tcp_flags,
> -                                       odp_actions, recircs, ukey->xcache);
> -        } /* else delete; too expensive to revalidate */
> +                                       odp_actions, recircs, ukey->xcache,
> +                                       reason);
> +        } else {
> +            /* else delete; too expensive to revalidate */

See the previous review, as I think the following comment is more clear:

 /* Delete the flow as it's too expensive to revalidate. */

> +            *reason = FDR_TOO_EXPENSIVE;
> +        }
>      } else if (!push.n_packets || ukey->xcache
>                 || !populate_xcache(udpif, ukey, push.tcp_flags)) {
>          result = UKEY_KEEP;
> @@ -2720,6 +2743,7 @@ revalidate(struct revalidator *revalidator)
>              struct recirc_refs recircs = RECIRC_REFS_EMPTY_INITIALIZER;
>              struct dpif_flow_stats stats = f->stats;
>              enum reval_result result;
> +            enum flow_del_reason reason = FDR_FLOW_LIVE;
>              struct udpif_key *ukey;
>              bool already_dumped;
>              int error;
> @@ -2767,10 +2791,11 @@ revalidate(struct revalidator *revalidator)
>              }
>              if (kill_them_all || (used && used < now - max_idle)) {
>                  result = UKEY_DELETE;
> +                reason = FDR_FLOW_TIME_OUT;
>              } else {
>                  result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
>                                           reval_seq, &recircs,
> -                                         f->attrs.offloaded);
> +                                         f->attrs.offloaded, &reason);
>              }
>              ukey->dump_seq = dump_seq;
>
> @@ -2779,6 +2804,7 @@ revalidate(struct revalidator *revalidator)
>                  udpif_update_flow_pps(udpif, ukey, f);
>              }
>
> +            OVS_USDT_PROBE(revalidate, flow_result, reason, udpif, ukey);
>              if (result != UKEY_KEEP) {
>                  /* Takes ownership of 'recircs'. */
>                  reval_op_init(&ops[n_ops++], result, udpif, ukey, &recircs,
> @@ -2829,6 +2855,7 @@ revalidator_sweep__(struct revalidator *revalidator, 
> bool purge)
>          struct udpif_key *ukey;
>          struct umap *umap = &udpif->ukeys[i];
>          size_t n_ops = 0;
> +        enum flow_del_reason reason = FDR_FLOW_LIVE;
>
>          CMAP_FOR_EACH(ukey, cmap_node, &umap->cmap) {
>              enum ukey_state ukey_state;
> @@ -2855,7 +2882,8 @@ revalidator_sweep__(struct revalidator *revalidator, 
> bool purge)
>                      COVERAGE_INC(revalidate_missed_dp_flow);
>                      memset(&stats, 0, sizeof stats);
>                      result = revalidate_ukey(udpif, ukey, &stats, 
> &odp_actions,
> -                                             reval_seq, &recircs, false);
> +                                             reval_seq, &recircs, false,
> +                                             &reason);
>                  }
>                  if (result != UKEY_KEEP) {
>                      /* Clears 'recircs' if filled by revalidate_ukey(). */
> diff --git a/utilities/automake.mk b/utilities/automake.mk
> index eb57653a1..0f7d3adc1 100644
> --- a/utilities/automake.mk
> +++ b/utilities/automake.mk
> @@ -63,6 +63,7 @@ EXTRA_DIST += \
>       utilities/docker/debian/Dockerfile \
>       utilities/docker/debian/build-kernel-modules.sh \
>       utilities/usdt-scripts/bridge_loop.bt \
> +     utilities/usdt-scripts/filter_probe.py \
>       utilities/usdt-scripts/upcall_cost.py \
>       utilities/usdt-scripts/upcall_monitor.py
>  MAN_ROOTS += \
> @@ -133,6 +134,7 @@ FLAKE8_PYFILES += utilities/ovs-pcap.in \
>       utilities/ovs-check-dead-ifs.in \
>       utilities/ovs-tcpdump.in \
>       utilities/ovs-pipegen.py \
> +     utilities/usdt-scripts/filter_probe.py \
>       utilities/usdt-scripts/upcall_monitor.py \
>       utilities/usdt-scripts/upcall_cost.py
>
> diff --git a/utilities/usdt-scripts/filter_probe.py 
> b/utilities/usdt-scripts/filter_probe.py
> new file mode 100755
> index 000000000..1aac5d44c
> --- /dev/null
> +++ b/utilities/usdt-scripts/filter_probe.py

I think the name is not that intuitive what about something like 
revalidate_monitor.py, or flow_delete_monitor.py?

For the script itself, I had quite some comments, and as I'm on PTO starting 
today for three weeks, I thought it might be easier (and faster for me) to just 
send a diff of things I think will require changes.
However I was still running out of time, so I did not get a chance to change 
the "ufid" field in struct event_t to the ovs_u128 type, and look at the filter 
code.

We can discuss this more after my PTO as I have very limited email access, or 
someone else can review the remaining part.


diff --git a/utilities/usdt-scripts/filter_probe.py 
b/utilities/usdt-scripts/filter_probe.py
index 1aac5d44c..9c007d340 100755
--- a/utilities/usdt-scripts/filter_probe.py
+++ b/utilities/usdt-scripts/filter_probe.py
@@ -91,6 +91,7 @@ import psutil
 import struct
 import sys
 import time
+
 #
 # eBPF source code
 #
@@ -98,21 +99,16 @@ bpf_src = """
 #include <linux/types.h>
 #include <uapi/linux/ptrace.h>

-#define MAX_KEY     2048
+#define MAX_KEY      2048
 #define FLOW_FILTER  <FILTER_BOOL>

+enum probe { OP_FLOW_PUT, FLOW_RESULT };

-enum probe { PUT, REVAL };
 typedef union ovs_u128 {
     u32 ufid32[4];
     u64 ufid64[2];
 } ovs_u128;

-struct nlattr {
-    u16 len;
-    u16 type;
-};
-
 struct dpif_flow_put {
     int flags;
     void *key_ptr;
@@ -136,7 +132,7 @@ struct udpif_key {
 struct event_t {
     u64 ts;
     u32 reason;
-    u32 ufid[4];
+    u32 ufid[4];   /* FIXME: Change this also to the ovs_u128 type. */
     u64 key_size;
     unsigned char key[MAX_KEY];
     enum probe probe;
@@ -145,46 +141,58 @@ struct event_t {
 BPF_HASH(watchlist, ovs_u128);
 BPF_RINGBUF_OUTPUT(events, <BUFFER_PAGE_COUNT>);

-int watch_reval(struct pt_regs *ctx) {
+int usdt__flow_result(struct pt_regs *ctx) {
     u64 *ufid_present = NULL;
-    struct udpif_key u;
-    bpf_usdt_readarg_p(3, ctx, &u, sizeof(struct udpif_key));
-    ovs_u128 ufid = u.ufid;
+    struct udpif_key ukey;
+
+    bpf_usdt_readarg_p(3, ctx, &ukey, sizeof ukey);
+    ovs_u128 ufid = ukey.ufid;
     ufid_present = watchlist.lookup(&ufid);
-    if(FLOW_FILTER && !ufid_present)
+
+    if(FLOW_FILTER && !ufid_present) {
         return 0;
-    struct event_t *data = events.ringbuf_reserve(sizeof(struct event_t));
-    /* If we can't reserve the space we need for the ring buffer, return 1 */
-    if(!data)
+    }
+
+    struct event_t *event = events.ringbuf_reserve(sizeof(struct event_t));
+    if(!event) {
+        /* If we can't reserve the space in the ring buffer, return 1. */
         return 1;
-    data->probe = REVAL;
-    data->ts = bpf_ktime_get_ns();
-    bpf_probe_read(&data->ufid, sizeof(ufid), &ufid);
-    bpf_usdt_readarg(1, ctx, &data->reason);
-    events.ringbuf_submit(data, 0);
+    }
+
+    event->probe = FLOW_RESULT;
+    event->ts = bpf_ktime_get_ns();
+    bpf_probe_read(&event->ufid, sizeof ufid, &ufid);
+    bpf_usdt_readarg(1, ctx, &event->reason);
+    events.ringbuf_submit(event, 0);
+
     return 0;
 };


-int watch_put(struct pt_regs *ctx) {
-    struct event_t *data = events.ringbuf_reserve(sizeof(struct event_t));
-    struct dpif_flow_put f;
-    struct nlattr nla;
+int usdt__op_flow_put(struct pt_regs *ctx) {
+    struct dpif_flow_put put;
     ovs_u128 ufid;
-    if(!data)
+
+    struct event_t *event = events.ringbuf_reserve(sizeof(struct event_t));
+    if(!event) {
+        /* If we can't reserve the space in the ring buffer, return 1. */
         return 1;
-    data->probe = PUT;
-    data->ts = bpf_ktime_get_ns();
-    bpf_usdt_readarg_p(2, ctx, &f, sizeof(struct dpif_flow_put));
-    bpf_probe_read(&data->ufid, sizeof(data->ufid), (void *) f.ufid_ptr);
-    bpf_probe_read(&ufid, sizeof(ufid), &data->ufid);
-    if (f.key_len > MAX_KEY) // verifier fails without this check.
-        f.key_len = MAX_KEY;
-    data->key_size = f.key_len;
-    bpf_probe_read(&data->key, f.key_len, (void*)f.key_ptr);
+    }
+
+    event->probe = OP_FLOW_PUT;
+    event->ts = bpf_ktime_get_ns();
+    bpf_usdt_readarg_p(2, ctx, &put, sizeof put);
+    bpf_probe_read(&event->ufid, sizeof event->ufid, put.ufid_ptr);
+    bpf_probe_read(&ufid, sizeof ufid , &event->ufid);
+    if (put.key_len > MAX_KEY) {
+        put.key_len = MAX_KEY;
+    }
+    event->key_size = put.key_len;
+    bpf_probe_read(&event->key, put.key_len, put.key_ptr);
+    event->reason = 0;
+    events.ringbuf_submit(event, 0);
+
     watchlist.increment(ufid);
-    data->reason = 0;
-    events.ringbuf_submit(data, 0);
     return 0;
 };
 """
@@ -194,10 +202,9 @@ int watch_put(struct pt_regs *ctx) {
 # format_ufid()
 #
 def format_ufid(ufid):
-    result = "ufid:%08x-%04x-%04x-%04x-%04x%08x" \
-             % (ufid[0], ufid[1] >> 16, ufid[1] & 0xffff,
-                ufid[2] >> 16, ufid[2] & 0, ufid[3])
-    return result
+    return "ufid:{:08x}-{:04x}-{:04x}-{:04x}-{:04x}{:08x}".format(
+        ufid[0], ufid[1] >> 16, ufid[1] & 0xffff,
+        ufid[2] >> 16, ufid[2] & 0, ufid[3])


 #
@@ -219,19 +226,21 @@ def handle_flow_put(event):
     if args.flow_keys or args.filter_flows is not None:
         key = decode_key(bytes(event.key)[:event.key_size])
         flow_dict, flow_str = parse_flow_dict(key)
-        # for each attribute that we're watching
+        # For each attribute that we're watching.
         if args.filter_flows is not None:
             if not compare_dicts(args.filter_flows, flow_dict):
-                # print("ignoring a flow")
                 find_and_delete_from_watchlist(event)
                 return
+
     print("{:<18.9f} {:<45} {:<13}".format(event.ts / 1000000000,
-          format_ufid(event.ufid), "flow_put"))
+          format_ufid(event.ufid), "Insert (put) flow to kernel"))
+
     if args.flow_keys:
         if len(flow_str) > 80:
             flow_str = "    " + "),\n    ".join(flow_str.split("), "))
-        print("{} has the following flow information:".
-              format(format_ufid(event.ufid)))
+        else:
+            flow_str = "    " + flow_str
+        print("  - It holds the following flow information:")
         print(flow_str)


@@ -239,6 +248,7 @@ def handle_flow_put(event):
 # compare_dicts()
 #
 def compare_dicts(filter, target):
+    # FIXME: filter is a reserved key word, so use something else.
     for key in filter:
         if key not in target:
             return False
@@ -282,12 +292,20 @@ def parse_flow_str(flow_str):
 # print_expiration()
 #
 def print_expiration(event):
+    reasons = ["Unknown flow expire reason!", "Flow timed out",
+               "Flow revalidation too expensive",
+               "Flow needs narrower wildcard mask",
+               "Bad ODP flow fit", "Flow with associated ofproto",
+               "Flow translation error", "Flow cache avoidance"]
+
     ufid_str = format_ufid(event.ufid)
-    reasons = ["Flow timed out", "Revalidation too expensive",
-               "Flow wildcards", "Bad ODP fit", "Associated ofproto",
-               "Translation error", "Cache avoidance"]
+    reason = event.reason
+
+    if reason not in range(0, len(reasons) - 1):
+        reason = 0
+
     print("{:<18.9f} {:<45} {:<17}".
-          format(event.ts / 1000000000, ufid_str, reasons[event.reason - 1]))
+          format(event.ts / 1000000000, ufid_str, reasons[reason]))


 #
@@ -350,8 +368,10 @@ def get_ovs_key_attr_str(attr):
                     "ct_tuple4",
                     "ct_tuple6",
                     "nsh"]
+
     if attr < 0 or attr > len(ovs_key_attr):
         return "<UNKNOWN>: {}".format(attr)
+
     return ovs_key_attr[attr]


@@ -361,11 +381,12 @@ def get_ovs_key_attr_str(attr):
 def is_nonzero(val):
     if isinstance(val, int):
         return (val != 0)
-    else:
-        if isinstance(val, str):
-            val = bytes(val, 'utf-8')
-        # if it's not a string or an int, it's bytes.
-        return (val.count(0) < len(val))
+
+    if isinstance(val, str):
+        val = bytes(val, 'utf-8')
+
+    # If it's not a string or an int, it's bytes.
+    return (val.count(0) < len(val))


 #
@@ -475,68 +496,104 @@ def handle_event(ctx, data, size):
     # 1. It's a revalidator probe and the reason is nonzero: A flow is expiring
     # 2. It's a revalidator probe and the reason is zero: flow revalidated
     # 3. It's a flow_put probe.
+    #
+    # We will ignore item 2, all others we report.
+    #
     event = b["events"].event(data)
-    if event.probe and event.reason:
-        print_expiration(event)
-    if not event.probe:
+    if event.probe == 0:  # OP_FLOW_PUT
         handle_flow_put(event)
+    elif event.probe == 1 and event.reason > 0:  # FLOW_RESULT
+        print_expiration(event)


 def main():
+    #
+    # Don't like these globals, but ctx passing does not seem to work with the
+    # existing open_ring_buffer() API :(
+    #
     global b
     global args
+
+    #
     # Argument parsing
+    #
     parser = argparse.ArgumentParser()
     parser.add_argument("--buffer-page-count",
                         help="Number of BPF ring buffer pages, default 1024",
                         type=int, default=1024, metavar="NUMBER")
     parser.add_argument("-k", "--flow-keys",
                         help="Print flow keys as flow strings",
-                        type=bool, const=True, default=False, nargs="?")
+                        action="store_true")
     parser.add_argument("--pid", "-p", metavar="VSWITCHD_PID",
                         help="ovs-vswitchd's PID", type=int, default=None)
     parser.add_argument("-D", "--debug", help="Enable eBPF debugging",
                         type=int, const=0x3f, default=0, nargs="?")
-    parser.add_argument("-f", "--filter-flows", metavar="FLOW STRING",
+    parser.add_argument("-f", "--filter-flows", metavar="FLOW_STRING",
                         help="Filter flows that match the specified flow",
                         type=str, default=None, nargs="*")
     args = parser.parse_args()
-    vswitch_pid = args.pid
-    # If we didn't specify the PID for ovs-vswitchd, find its PID.
-    if vswitch_pid is None:
+
+    #
+    # Find the PID of the ovs-vswitchd daemon if not specified.
+    #
+    if args.pid is None:
         for proc in psutil.process_iter():
-            if "ovs-vswitchd" in proc.name():
-                if vswitch_pid is not None:
-                    print("Error: Multiple ovs-vswitchd daemons running. "
-                          "Use the -p option to specify one to track.")
+            if 'ovs-vswitchd' in proc.name():
+                if args.pid is not None:
+                    print("ERROR: Multiple ovs-vswitchd daemons running, "
+                          "use the -p option!")
                     sys.exit(-1)
-                vswitch_pid = proc.pid
-    if vswitch_pid is None:
-        print("Error: is ovs-vswitchd running?")
+
+                args.pid = proc.pid
+    #
+    # Error checking on input parameters
+    #
+    if args.pid is None:
+        print("ERROR: Failed to find ovs-vswitchd's PID!")
         sys.exit(-1)
-    u = USDT(pid=int(vswitch_pid))
+
+    #
+    # Attach the usdt probes
+    #
+    u = USDT(pid=int(args.pid))
     try:
-        u.enable_probe(probe="op_flow_put", fn_name="watch_put")
+        u.enable_probe(probe="op_flow_put", fn_name="usdt__op_flow_put")
     except USDTException as e:
-        print("Error attaching flow_put probe.")
+        print("Error attaching the dpif_netlink_operate__:op_flow_put probe.")
         print(str(e))
         sys.exit(-1)
+
     try:
-        u.enable_probe(probe="flow_result", fn_name="watch_reval")
+        u.enable_probe(probe="flow_result", fn_name="usdt__flow_result")
     except USDTException as e:
-        print("Error attaching revalidator_deletion probe.")
+        print("Error attaching the revalidate:flow_result probe.")
         print(str(e))
         sys.exit(-1)
-    filter_bool = 0
-    if args.filter_flows is not None:
+
+    #
+    # Attach probe to running process
+    #
+    if args.filter_flows is None:
+        filter_bool = 0
+    else:
         filter_bool = 1
         args.filter_flows = parse_flow_str(args.filter_flows[0])
+
     source = bpf_src.replace("<BUFFER_PAGE_COUNT>",
                              str(args.buffer_page_count))
     source = source.replace("<FILTER_BOOL>", str(filter_bool))
+
     b = BPF(text=source, usdt_contexts=[u], debug=args.debug)
-    b["events"].open_ring_buffer(handle_event)
+
+    #
+    # Print header
+    #
     print("{:<18} {:<45} {:<17}".format("TIME", "UFID", "EVENT/REASON"))
+
+    #
+    # Dump out all events
+    #
+    b["events"].open_ring_buffer(handle_event)
     while 1:
         try:
             b.ring_buffer_poll()
@@ -545,5 +602,8 @@ def main():
             break


+#
+# Start main() as the default entry point...
+#
 if __name__ == "__main__":
     main()





_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to