aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/openvswitch.h4
-rw-r--r--net/openvswitch/datapath.c14
2 files changed, 11 insertions, 7 deletions
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 970553cbbc8e..0b979ee4bfc0 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -395,7 +395,9 @@ struct ovs_key_nd {
395 * @OVS_FLOW_ATTR_ACTIONS: Nested %OVS_ACTION_ATTR_* attributes specifying 395 * @OVS_FLOW_ATTR_ACTIONS: Nested %OVS_ACTION_ATTR_* attributes specifying
396 * the actions to take for packets that match the key. Always present in 396 * the actions to take for packets that match the key. Always present in
397 * notifications. Required for %OVS_FLOW_CMD_NEW requests, optional for 397 * notifications. Required for %OVS_FLOW_CMD_NEW requests, optional for
398 * %OVS_FLOW_CMD_SET requests. 398 * %OVS_FLOW_CMD_SET requests. An %OVS_FLOW_CMD_SET without
399 * %OVS_FLOW_ATTR_ACTIONS will not modify the actions. To clear the actions,
400 * an %OVS_FLOW_ATTR_ACTIONS without any nested attributes must be given.
399 * @OVS_FLOW_ATTR_STATS: &struct ovs_flow_stats giving statistics for this 401 * @OVS_FLOW_ATTR_STATS: &struct ovs_flow_stats giving statistics for this
400 * flow. Present in notifications if the stats would be nonzero. Ignored in 402 * flow. Present in notifications if the stats would be nonzero. Ignored in
401 * requests. 403 * requests.
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 8867d7e2d65b..90a1e5e66287 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -810,6 +810,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
810 goto err_kfree; 810 goto err_kfree;
811 } 811 }
812 } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { 812 } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) {
813 /* OVS_FLOW_CMD_NEW must have actions. */
813 error = -EINVAL; 814 error = -EINVAL;
814 goto error; 815 goto error;
815 } 816 }
@@ -849,8 +850,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
849 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); 850 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
850 } else { 851 } else {
851 /* We found a matching flow. */ 852 /* We found a matching flow. */
852 struct sw_flow_actions *old_acts;
853
854 /* Bail out if we're not allowed to modify an existing flow. 853 /* Bail out if we're not allowed to modify an existing flow.
855 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL 854 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
856 * because Generic Netlink treats the latter as a dump 855 * because Generic Netlink treats the latter as a dump
@@ -866,11 +865,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
866 if (!ovs_flow_cmp_unmasked_key(flow, &match)) 865 if (!ovs_flow_cmp_unmasked_key(flow, &match))
867 goto err_unlock_ovs; 866 goto err_unlock_ovs;
868 867
869 /* Update actions. */ 868 /* Update actions, if present. */
870 old_acts = ovsl_dereference(flow->sf_acts); 869 if (acts) {
871 rcu_assign_pointer(flow->sf_acts, acts); 870 struct sw_flow_actions *old_acts;
872 ovs_nla_free_flow_actions(old_acts);
873 871
872 old_acts = ovsl_dereference(flow->sf_acts);
873 rcu_assign_pointer(flow->sf_acts, acts);
874 ovs_nla_free_flow_actions(old_acts);
875 }
874 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); 876 reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
875 877
876 /* Clear stats. */ 878 /* Clear stats. */