diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 3d5feede962d..23fd4fbd11e2 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -824,23 +824,6 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key, return 0; } -/* Lookup connection and confirm if unconfirmed. */ -static int ovs_ct_commit(struct net *net, struct sw_flow_key *key, - const struct ovs_conntrack_info *info, - struct sk_buff *skb) -{ - int err; - - err = __ovs_ct_lookup(net, key, info, skb); - if (err) - return err; - /* This is a no-op if the connection has already been confirmed. */ - if (nf_conntrack_confirm(skb) != NF_ACCEPT) - return -EINVAL; - - return 0; -} - static bool labels_nonzero(const struct ovs_key_ct_labels *labels) { size_t i; @@ -873,21 +856,33 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb, } if (info->commit) - err = ovs_ct_commit(net, key, info, skb); + err = __ovs_ct_lookup(net, key, info, skb); else err = ovs_ct_lookup(net, key, info, skb); if (err) goto err; + /* Apply changes before confirming the connection so that the initial + * conntrack NEW netlink event carries the values given in the CT + * action. + */ if (info->mark.mask) { err = ovs_ct_set_mark(skb, key, info->mark.value, info->mark.mask); if (err) goto err; } - if (labels_nonzero(&info->labels.mask)) + if (labels_nonzero(&info->labels.mask)) { err = ovs_ct_set_labels(skb, key, &info->labels.value, &info->labels.mask); + if (err) + goto err; + } + /* This will take care of sending queued events even if the connection + * is already confirmed. + */ + if (info->commit && nf_conntrack_confirm(skb) != NF_ACCEPT) + err = -EINVAL; err: skb_push(skb, nh_ofs); if (err)