summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/odp-util.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 5da83b4c6..874350325 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -4008,6 +4008,7 @@ odp_flow_format(const struct nlattr *key, size_t key_len,
const struct nlattr *a;
unsigned int left;
bool has_ethtype_key = false;
+ bool has_packet_type_key = false;
struct ofpbuf ofp;
bool first_field = true;
@@ -4028,6 +4029,8 @@ odp_flow_format(const struct nlattr *key, size_t key_len,
if (attr_type == OVS_KEY_ATTR_ETHERTYPE) {
has_ethtype_key = true;
+ } else if (attr_type == OVS_KEY_ATTR_PACKET_TYPE) {
+ has_packet_type_key = true;
}
is_nested_attr = odp_key_attr_len(ovs_flow_key_attr_lens,
@@ -4050,6 +4053,34 @@ odp_flow_format(const struct nlattr *key, size_t key_len,
}
format_odp_key_attr__(a, ma, portno_names, ds, verbose);
first_field = false;
+ } else if (attr_type == OVS_KEY_ATTR_ETHERNET
+ && !has_packet_type_key) {
+ /* This special case reflects differences between the kernel
+ * and userspace datapaths regarding the root type of the
+ * packet being matched (typically Ethernet but some tunnels
+ * can encapsulate IPv4 etc.). The kernel datapath does not
+ * have an explicit way to indicate packet type; instead:
+ *
+ * - If OVS_KEY_ATTR_ETHERNET is present, the packet is an
+ * Ethernet packet and OVS_KEY_ATTR_ETHERTYPE is the
+ * Ethertype encoded in the Ethernet header.
+ *
+ * - If OVS_KEY_ATTR_ETHERNET is absent, then the packet's
+ * root type is that encoded in OVS_KEY_ATTR_ETHERTYPE
+ * (i.e. if OVS_KEY_ATTR_ETHERTYPE is 0x0800 then the
+ * packet is an IPv4 packet).
+ *
+ * Thus, if OVS_KEY_ATTR_ETHERNET is present, even if it is
+ * all-wildcarded, it is important to print it.
+ *
+ * On the other hand, the userspace datapath supports
+ * OVS_KEY_ATTR_PACKET_TYPE and uses it to indicate the packet
+ * type. Thus, if OVS_KEY_ATTR_PACKET_TYPE is present, we need
+ * not print an all-wildcarded OVS_KEY_ATTR_ETHERNET. */
+ if (!first_field) {
+ ds_put_char(ds, ',');
+ }
+ ds_put_cstr(ds, "eth()");
}
ofpbuf_clear(&ofp);
}