Use netlink_has_listeners() and NLM_F_ECHO flag to determine if a reply is needed or not.
Signed-off-by: Jarno Rajahalme <jrajaha...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev