@@ -95,6 +95,9 @@ enum ovs_datapath_attr {
* per-cpu dispatch mode
*/
OVS_DP_ATTR_IFINDEX,
+ OVS_DP_ATTR_EXCLUDE_CMDS, /* u32 mask of OVS_PACKET_CMDs for
+ * omitting FLOW_KEY attribute
+ */
__OVS_DP_ATTR_MAX
};
@@ -138,6 +141,9 @@ struct ovs_vport_stats {
/* Allow per-cpu dispatch of upcalls */
#define OVS_DP_F_DISPATCH_UPCALL_PER_CPU (1 << 3)
+/* Drop Flow key data from upcall packet cmds */
+#define OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY (1 << 4)
+
/* Fixed logical ports. */
#define OVSP_LOCAL ((__u32)0)
@@ -470,9 +470,13 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
}
upcall->dp_ifindex = dp_ifindex;
- err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false, user_skb);
- if (err)
- goto out;
+ if (!(dp->user_features & OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY) ||
+ !(dp->upcall_exclude_cmds & (1U << upcall_info->cmd))) {
+ err = ovs_nla_put_key(key, key, OVS_PACKET_ATTR_KEY, false,
+ user_skb);
+ if (err)
+ goto out;
+ }
if (upcall_info->userdata)
__nla_put(user_skb, OVS_PACKET_ATTR_USERDATA,
@@ -1526,6 +1530,7 @@ static size_t ovs_dp_cmd_msg_size(void)
msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */
msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_MASKS_CACHE_SIZE */
msgsize += nla_total_size(sizeof(u32) * nr_cpu_ids); /* OVS_DP_ATTR_PER_CPU_PIDS */
+ msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_EXCLUDE_CMDS */
return msgsize;
}
@@ -1574,6 +1579,10 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
goto nla_put_failure;
}
+ if (nla_put_u32(skb, OVS_DP_ATTR_EXCLUDE_CMDS,
+ dp->upcall_exclude_cmds))
+ goto nla_put_failure;
+
genlmsg_end(skb, ovs_header);
return 0;
@@ -1684,7 +1693,8 @@ static int ovs_dp_change(struct datapath *dp, struct nlattr *a[])
if (user_features & ~(OVS_DP_F_VPORT_PIDS |
OVS_DP_F_UNALIGNED |
OVS_DP_F_TC_RECIRC_SHARING |
- OVS_DP_F_DISPATCH_UPCALL_PER_CPU))
+ OVS_DP_F_DISPATCH_UPCALL_PER_CPU |
+ OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY))
return -EOPNOTSUPP;
#if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
@@ -1705,6 +1715,14 @@ static int ovs_dp_change(struct datapath *dp, struct nlattr *a[])
dp->user_features = user_features;
+ if (dp->user_features & OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY) {
+ if (!a[OVS_DP_ATTR_EXCLUDE_CMDS])
+ return -EINVAL;
+
+ dp->upcall_exclude_cmds =
+ nla_get_u32(a[OVS_DP_ATTR_EXCLUDE_CMDS]);
+ }
+
if (dp->user_features & OVS_DP_F_DISPATCH_UPCALL_PER_CPU &&
a[OVS_DP_ATTR_PER_CPU_PIDS]) {
/* Upcall Netlink Port IDs have been updated */
@@ -101,6 +101,8 @@ struct datapath {
u32 max_headroom;
+ u32 upcall_exclude_cmds;
+
/* Switch meters. */
struct dp_meter_table meter_tbl;
When processing upcall commands, two groups of data are available to userspace for processing: the actual packet data and the kernel sw flow key data. The inclusion of the flow key allows the userspace avoid running through the dissection again. However, the userspace can choose to ignore the flow key data, as is the case in some ovs-vswitchd upcall processing. For these messages, having the flow key data merely adds additional data to the upcall pipeline without any actual gain. Userspace simply throws the data away anyway. Introduce a new feature OVS_DP_F_EXCLUDE_UPCALL_FLOW_KEY which signals that the userspace doesn't want upcalls included with specific class of message (for example MISS messages). The associated attribute OVS_DP_ATTR_EXCLUDE_CMDS tells which specific commands to omit via a bitmask. A test will be added to showcase using the feature. Signed-off-by: Aaron Conole <aconole@redhat.com> --- include/uapi/linux/openvswitch.h | 6 ++++++ net/openvswitch/datapath.c | 26 ++++++++++++++++++++++---- net/openvswitch/datapath.h | 2 ++ 3 files changed, 30 insertions(+), 4 deletions(-)