Most of commands in ovs-ofctl and ovs-appctl can display port names
instead of port numbers by using --names option. This change adds
similar functionality to ofproto/trace.

For backward compatibility, the default behavior is the same as
before.

Signed-off-by: Nobuhiro MIKI <[email protected]>
--
v2:
* fix NEWS
---
 NEWS                          |  3 ++
 ofproto/ofproto-dpif-trace.c  | 80 +++++++++++++++++++++++++++--------
 ofproto/ofproto-dpif-trace.h  |  5 ++-
 ofproto/ofproto-dpif-upcall.c |  3 +-
 ofproto/ofproto-dpif-xlate.c  | 24 ++++++++++-
 ofproto/ofproto-dpif-xlate.h  |  4 ++
 tests/ofproto-dpif.at         | 12 ++++++
 7 files changed, 109 insertions(+), 22 deletions(-)

diff --git a/NEWS b/NEWS
index 53594cbbd..843abc7ac 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 Post-v3.0.0
 --------------------
+   - ovs-appctl:
+     * "ovs-appctl ofproto/trace" command can now display port names with the
+       "--names" option.
 
 
 v3.0.0 - 15 Aug 2022
diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
index 109940ad2..527e2f17e 100644
--- a/ofproto/ofproto-dpif-trace.c
+++ b/ofproto/ofproto-dpif-trace.c
@@ -213,7 +213,7 @@ parse_flow_and_packet(int argc, const char *argv[],
                       struct ofproto_dpif **ofprotop, struct flow *flow,
                       struct dp_packet **packetp,
                       struct ovs_list *next_ct_states,
-                      bool *consistent)
+                      bool *consistent, bool *names)
 {
     const struct dpif_backer *backer = NULL;
     char *error = NULL;
@@ -233,6 +233,9 @@ parse_flow_and_packet(int argc, const char *argv[],
     if (consistent) {
         *consistent = false;
     }
+    if (names) {
+        *names = false;
+    }
     for (int i = 1; i < argc; i++) {
         const char *arg = argv[i];
         if (!strcmp(arg, "-generate") || !strcmp(arg, "--generate")) {
@@ -270,6 +273,10 @@ parse_flow_and_packet(int argc, const char *argv[],
                    && (!strcmp(arg, "-consistent") ||
                        !strcmp(arg, "--consistent"))) {
             *consistent = true;
+        } else if (names
+                   && (!strcmp(arg, "-names") ||
+                       !strcmp(arg, "--names"))) {
+            *names = true;
         } else if (!strcmp(arg, "--ct-next")) {
             if (i + 1 >= argc) {
                 error = xasprintf("Missing argument for option %s", arg);
@@ -418,11 +425,7 @@ parse_flow_and_packet(int argc, const char *argv[],
         }
 
         struct ofputil_port_map map = OFPUTIL_PORT_MAP_INITIALIZER(&map);
-        const struct ofport *ofport;
-        HMAP_FOR_EACH (ofport, hmap_node, &(*ofprotop)->up.ports) {
-            ofputil_port_map_put(&map, ofport->ofp_port,
-                                 netdev_get_name(ofport->netdev));
-        }
+        ofproto_append_ports_to_map(&map, (*ofprotop)->up.ports);
         char *err = parse_ofp_exact_flow(flow, NULL,
                                          ofproto_get_tun_tab(&(*ofprotop)->up),
                                          args[n_args - 1], &map);
@@ -474,16 +477,17 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int 
argc, const char *argv[],
     struct dp_packet *packet;
     char *error;
     struct flow flow;
+    bool names;
     struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states);
 
     error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet,
-                                  &next_ct_states, NULL);
+                                  &next_ct_states, NULL, &names);
     if (!error) {
         struct ds result;
 
         ds_init(&result);
         ofproto_trace(ofproto, &flow, packet, NULL, 0, &next_ct_states,
-                      &result);
+                      &result, names);
         unixctl_command_reply(conn, ds_cstr(&result));
         ds_destroy(&result);
         dp_packet_delete(packet);
@@ -501,6 +505,7 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, 
int argc,
     enum ofputil_protocol usable_protocols;
     struct ofproto_dpif *ofproto;
     bool enforce_consistency;
+    bool names;
     struct ofpbuf ofpacts;
     struct dp_packet *packet;
     struct ds result;
@@ -530,7 +535,8 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, 
int argc,
     }
 
     error = parse_flow_and_packet(argc, argv, &ofproto, &match.flow, &packet,
-                                  &next_ct_states, &enforce_consistency);
+                                  &next_ct_states, &enforce_consistency,
+                                  &names);
     if (error) {
         unixctl_command_reply_error(conn, error);
         free(error);
@@ -578,7 +584,8 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, 
int argc,
     }
 
     ofproto_trace(ofproto, &match.flow, packet,
-                  ofpacts.data, ofpacts.size, &next_ct_states, &result);
+                  ofpacts.data, ofpacts.size, &next_ct_states, &result,
+                  names);
     unixctl_command_reply(conn, ds_cstr(&result));
 
 exit:
@@ -729,7 +736,7 @@ static void
 ofproto_trace__(struct ofproto_dpif *ofproto, const struct flow *flow,
                 const struct dp_packet *packet, struct ovs_list *recirc_queue,
                 const struct ofpact ofpacts[], size_t ofpacts_len,
-                struct ds *output)
+                struct ds *output, bool names)
 {
     struct ofpbuf odp_actions;
     ofpbuf_init(&odp_actions, 0);
@@ -737,6 +744,8 @@ ofproto_trace__(struct ofproto_dpif *ofproto, const struct 
flow *flow,
     struct xlate_in xin;
     struct flow_wildcards wc;
     struct ovs_list trace = OVS_LIST_INITIALIZER(&trace);
+    struct ofputil_port_map map = OFPUTIL_PORT_MAP_INITIALIZER(&map);
+    struct hmap *portno_names = NULL;
     xlate_in_init(&xin, ofproto,
                   ofproto_dpif_get_tables_version(ofproto), flow,
                   flow->in_port.ofp_port, NULL, ntohs(flow->tcp_flags),
@@ -745,12 +754,27 @@ ofproto_trace__(struct ofproto_dpif *ofproto, const 
struct flow *flow,
     xin.ofpacts_len = ofpacts_len;
     xin.trace = &trace;
     xin.recirc_queue = recirc_queue;
+    xin.names = names;
+
+    if (names) {
+        ofproto_append_ports_to_map(&map, ofproto->up.ports);
+
+        portno_names = xmalloc(sizeof *portno_names);
+        hmap_init(portno_names);
+
+        struct dpif_port dpif_port;
+        struct dpif_port_dump port_dump;
+        DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, ofproto->backer->dpif) {
+            odp_portno_names_set(portno_names, dpif_port.port_no,
+                                 dpif_port.name);
+        }
+    }
 
     /* Copy initial flow out of xin.flow.  It differs from '*flow' because
      * xlate_in_init() initializes actset_output to OFPP_UNSET. */
     struct flow initial_flow = xin.flow;
     ds_put_cstr(output, "Flow: ");
-    flow_format(output, &initial_flow, NULL);
+    flow_format(output, &initial_flow, &map);
     ds_put_char(output, '\n');
 
     struct xlate_out xout;
@@ -762,18 +786,19 @@ ofproto_trace__(struct ofproto_dpif *ofproto, const 
struct flow *flow,
     if (flow_equal(&initial_flow, &xin.flow)) {
         ds_put_cstr(output, "unchanged");
     } else {
-        flow_format(output, &xin.flow, NULL);
+        flow_format(output, &xin.flow, &map);
     }
     ds_put_char(output, '\n');
 
     ds_put_cstr(output, "Megaflow: ");
     struct match match;
     match_init(&match, flow, &wc);
-    match_format(&match, NULL, output, OFP_DEFAULT_PRIORITY);
+    match_format(&match, &map, output, OFP_DEFAULT_PRIORITY);
     ds_put_char(output, '\n');
 
     ds_put_cstr(output, "Datapath actions: ");
-    format_odp_actions(output, odp_actions.data, odp_actions.size, NULL);
+    format_odp_actions(output, odp_actions.data, odp_actions.size,
+                       portno_names);
 
     if (error != XLATE_OK) {
         ds_put_format(output,
@@ -790,6 +815,13 @@ ofproto_trace__(struct ofproto_dpif *ofproto, const struct 
flow *flow,
         }
     }
 
+    if (names) {
+        ofputil_port_map_destroy(&map);
+
+        odp_portno_names_destroy(portno_names);
+        hmap_destroy(portno_names);
+        free(portno_names);
+    }
 
     xlate_out_uninit(&xout);
     ofpbuf_uninit(&odp_actions);
@@ -809,17 +841,19 @@ void
 ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
               const struct dp_packet *packet,
               const struct ofpact ofpacts[], size_t ofpacts_len,
-              struct ovs_list *next_ct_states, struct ds *output)
+              struct ovs_list *next_ct_states, struct ds *output,
+              bool names)
 {
     struct ovs_list recirc_queue = OVS_LIST_INITIALIZER(&recirc_queue);
     ofproto_trace__(ofproto, flow, packet, &recirc_queue,
-                    ofpacts, ofpacts_len, output);
+                    ofpacts, ofpacts_len, output, names);
 
     struct oftrace_recirc_node *recirc_node;
     LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) {
         ofproto_trace_recirc_node(recirc_node, next_ct_states, output);
         ofproto_trace__(ofproto, &recirc_node->flow, recirc_node->packet,
-                        &recirc_queue, ofpacts, ofpacts_len, output);
+                        &recirc_queue, ofpacts, ofpacts_len, output,
+                        names);
         oftrace_recirc_node_destroy(recirc_node);
     }
 }
@@ -843,3 +877,13 @@ ofproto_dpif_trace_init(void)
         "[-generate|packet] actions",
         2, INT_MAX, ofproto_unixctl_trace_actions, NULL);
 }
+
+void
+ofproto_append_ports_to_map(struct ofputil_port_map *map, struct hmap ports) {
+    struct ofport *ofport;
+
+    HMAP_FOR_EACH (ofport, hmap_node, &ports) {
+        ofputil_port_map_put(map, ofport->ofp_port,
+                             netdev_get_name(ofport->netdev));
+    }
+}
diff --git a/ofproto/ofproto-dpif-trace.h b/ofproto/ofproto-dpif-trace.h
index 4b04f1756..35c765e5d 100644
--- a/ofproto/ofproto-dpif-trace.h
+++ b/ofproto/ofproto-dpif-trace.h
@@ -86,7 +86,8 @@ void ofproto_dpif_trace_init(void);
 void ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
               const struct dp_packet *packet,
               const struct ofpact *, size_t ofpacts_len,
-              struct ovs_list *next_ct_states, struct ds *output);
+              struct ovs_list *next_ct_states, struct ds *output,
+              bool names);
 
 struct oftrace_node *oftrace_report(struct ovs_list *, enum oftrace_node_type,
                                     const char *text);
@@ -95,5 +96,7 @@ bool oftrace_add_recirc_node(struct ovs_list *recirc_queue,
                              const struct ofpact_nat *,
                              const struct dp_packet *, uint32_t recirc_id,
                              const uint16_t zone);
+void
+ofproto_append_ports_to_map(struct ofputil_port_map *map, struct hmap ports);
 
 #endif /* ofproto-dpif-trace.h */
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 57f94df54..88ae46f14 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -1246,7 +1246,8 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall,
         if (!VLOG_DROP_WARN(&rll)) {
             ds_init(&output);
             ofproto_trace(upcall->ofproto, upcall->flow,
-                          upcall->packet, NULL, 0, NULL, &output);
+                          upcall->packet, NULL, 0, NULL, &output,
+                          false);
             VLOG_WARN("%s", ds_cstr(&output));
             ds_destroy(&output);
         }
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index fda802e83..ee5146b1d 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -813,9 +813,20 @@ xlate_report_table(const struct xlate_ctx *ctx, struct 
rule_dpif *rule,
         ds_put_cstr(&s, "Packets are IP fragments and "
                     "the fragment handling mode is \"drop\".");
     } else {
+        struct ofputil_port_map map = OFPUTIL_PORT_MAP_INITIALIZER(&map);
+
+        if (ctx->xin->names) {
+            struct ofproto_dpif *ofprotop;
+            ofprotop = ofproto_dpif_lookup_by_name(ctx->xbridge->name);
+            ofproto_append_ports_to_map(&map, ofprotop->up.ports);
+        }
+
         minimatch_format(&rule->up.cr.match,
                          ofproto_get_tun_tab(&ctx->xin->ofproto->up),
-                         NULL, &s, OFP_DEFAULT_PRIORITY);
+                         &map, &s, OFP_DEFAULT_PRIORITY);
+
+        ofputil_port_map_destroy(&map);
+
         if (ds_last(&s) != ' ') {
             ds_put_cstr(&s, ", ");
         }
@@ -6985,11 +6996,20 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t 
ofpacts_len,
         }
 
         if (OVS_UNLIKELY(ctx->xin->trace)) {
+            struct ofputil_port_map map = OFPUTIL_PORT_MAP_INITIALIZER(&map);
+
+            if (ctx->xin->names) {
+                struct ofproto_dpif *ofprotop;
+                ofprotop = ofproto_dpif_lookup_by_name(ctx->xbridge->name);
+                ofproto_append_ports_to_map(&map, ofprotop->up.ports);
+            }
+
             struct ds s = DS_EMPTY_INITIALIZER;
-            struct ofpact_format_params fp = { .s = &s };
+            struct ofpact_format_params fp = { .s = &s, .port_map = &map };
             ofpacts_format(a, OFPACT_ALIGN(a->len), &fp);
             xlate_report(ctx, OFT_ACTION, "%s", ds_cstr(&s));
             ds_destroy(&s);
+            ofputil_port_map_destroy(&map);
         }
 
         switch (a->type) {
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 2ba90e999..3b51ccde2 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -166,6 +166,10 @@ struct xlate_in {
 
     /* UUID of first non-patch port packet was received on.*/
     struct uuid xport_uuid;
+
+    /* If true, port names is displayed instead of port numbers in
+     * tracing translation. */
+    bool names;
 };
 
 void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *,
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 2e91ae1a1..1a232ffed 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -6284,6 +6284,18 @@ Flow: 
pkt_mark=0x1,skb_priority=0x2,arp,in_port=2,vlan_tci=0x0000,dl_src=50:54:0
 bridge("br0")
 ])
 
+# Test command: ofproto/trace br_name br_flow packet --names
+AT_CHECK([ovs-appctl ofproto/trace br0 \
+  "in_port=2,skb_priority=2,pkt_mark=1" "$pkt2to1" --names], [0], 
[stdout],[stderr])
+AT_CHECK([tail -1 stdout], [0], [dnl
+Datapath actions: p1
+])
+AT_CHECK([head -n 3 stdout], [0], [dnl
+Flow: 
pkt_mark=0x1,skb_priority=0x2,arp,in_port=p2,vlan_tci=0x0000,dl_src=50:54:00:00:00:02,dl_dst=50:54:00:00:00:01,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_op=0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
+
+bridge("br0")
+])
+
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
-- 
2.36.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to