[ovs-dev] [PATCH v2 12/13] datapath: Build netlink reply only if needed.
Jarno Rajahalme
jrajahalme at nicira.com
Wed Feb 12 00:07:23 UTC 2014
Use netlink_has_listeners() and NLM_F_ECHO flag to determine if a
reply is needed or not.
Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
datapath/datapath.c | 57 +++++++++++++++++++++++++++++++--------------------
1 file changed, 35 insertions(+), 22 deletions(-)
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 90fdc60..9e86ec8 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -64,6 +64,15 @@
int ovs_net_id __read_mostly;
+/* Check if need to build a reply message.
+ * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
+static bool ovs_build_reply(struct genl_info *info,
+ const struct genl_multicast_group *grp)
+{
+ return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
+ netlink_has_listeners(genl_info_net(info)->genl_sock, grp->id);
+}
+
static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
struct genl_multicast_group *grp)
{
@@ -782,7 +791,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
struct sw_flow_key key, masked_key;
struct sw_flow *flow;
struct sw_flow_mask mask;
- struct sk_buff *reply;
+ struct sk_buff *reply = NULL;
struct datapath *dp;
struct sw_flow_actions *acts = NULL;
struct sw_flow_match match;
@@ -826,10 +835,12 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
goto error;
}
- reply = ovs_flow_cmd_alloc_info(acts, info);
- if (!reply) {
- error = -ENOMEM;
- goto err_kfree_acts;
+ if (ovs_build_reply(info, &ovs_dp_flow_multicast_group)) {
+ reply = ovs_flow_cmd_alloc_info(acts, info);
+ if (!reply) {
+ error = -ENOMEM;
+ goto err_kfree_acts;
+ }
}
ovs_lock();
@@ -893,13 +904,17 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
ovs_flow_stats_clear(flow);
}
- error = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, reply,
- info->snd_portid, info->snd_seq, 0,
- OVS_FLOW_CMD_NEW);
- BUG_ON(error < 0);
+ if (reply) {
+ error = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
+ reply, info->snd_portid,
+ info->snd_seq, 0,
+ OVS_FLOW_CMD_NEW);
+ BUG_ON(error < 0);
+ }
ovs_unlock();
- ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
+ if (reply)
+ ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
return 0;
err_unlock:
@@ -964,7 +979,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
struct nlattr **a = info->attrs;
struct ovs_header *ovs_header = info->userhdr;
struct sw_flow_key key;
- struct sk_buff *reply;
+ struct sk_buff *reply = NULL;
struct sw_flow *flow;
struct datapath *dp;
struct sw_flow_match match;
@@ -996,17 +1011,15 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
ovs_flow_tbl_remove(&dp->table, flow);
ovs_unlock();
- reply = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info);
- /* XXX: We may skip sending a response if kernel is out of memory.
- * We could do the allocation before locking if we did not need
- * to return the actions (which are useless in this case anyway). */
- if (reply) {
- err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
- reply, info->snd_portid,
- info->snd_seq, 0,
- OVS_FLOW_CMD_DEL);
- BUG_ON(err < 0);
- ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
+ if (ovs_build_reply(info, &ovs_dp_flow_multicast_group)) {
+ /* XXX: We may skip sending a response if kernel is out of
+ memory. We could do the allocation before locking if we did
+ not need to return the actions (which are useless in this
+ case anyway). */
+ reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
+ info, OVS_FLOW_CMD_DEL);
+ if (!IS_ERR(reply))
+ ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
}
ovs_flow_free(flow, true);
return 0;
--
1.7.10.4
More information about the dev
mailing list