+static void
+format_be32_masked(struct ds *s, const char *name,
+ ovs_be32 value, ovs_be32 mask)
+{
+ if (mask != htonl(0)) {
+ ds_put_format(s, "%s=", name);
+ if (mask == OVS_BE32_MAX) {
+ ds_put_format(s, "%"PRIu32, ntohl(value));
+ } else {
+ ds_put_format(s, "0x%"PRIx32"/0x%"PRIx32,
+ ntohl(value), ntohl(mask));
+ }
+ ds_put_char(s, ',');
+ }
+}
+
+static void
+format_uint32_masked(struct ds *s, const char *name,
+ uint32_t value, uint32_t mask)
+{
+ if (mask) {
+ ds_put_format(s, "%s=%#"PRIx32, name, value);
+ if (mask != UINT32_MAX) {
+ ds_put_format(s, "/%#"PRIx32, mask);
+ }
+ ds_put_char(s, ',');
+ }
+}
+
+static void
+format_be64_masked(struct ds *s, const char *name,
+ ovs_be64 value, ovs_be64 mask)
+{
+ if (mask != htonll(0)) {
+ ds_put_format(s, "%s=%#"PRIx64, name, ntohll(value));
+ if (mask != OVS_BE64_MAX) {
+ ds_put_format(s, "/%#"PRIx64, ntohll(mask));
+ }
+ ds_put_char(s, ',');
+ }
+}
+
+static void
+format_flow_tunnel(struct ds *s, const struct match *match)
+{
+ const struct flow_wildcards *wc = &match->wc;
+ const struct flow_tnl *tnl = &match->flow.tunnel;
+
+ format_be64_masked(s, "tun_id", tnl->tun_id, wc->masks.tunnel.tun_id);
+ format_ip_netmask(s, "tun_src", tnl->ip_src, wc->masks.tunnel.ip_src);
+ format_ip_netmask(s, "tun_dst", tnl->ip_dst, wc->masks.tunnel.ip_dst);
+
+ if (wc->masks.tunnel.ip_tos) {
+ ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
+ }
+ if (wc->masks.tunnel.ip_ttl) {
+ ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl);
+ }
+ if (wc->masks.tunnel.flags) {
+ format_flags(s, flow_tun_flag_to_string, tnl->flags, '|');
+ ds_put_char(s, ',');
+ }
+}
+