|
@@ -483,7 +483,11 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
|
|
|
* actually run the packet through conntrack twice unless it's for a
|
|
|
* different zone.
|
|
|
*/
|
|
|
- if (!skb_nfct_cached(net, key, info, skb)) {
|
|
|
+ bool cached = skb_nfct_cached(net, key, info, skb);
|
|
|
+ enum ip_conntrack_info ctinfo;
|
|
|
+ struct nf_conn *ct;
|
|
|
+
|
|
|
+ if (!cached) {
|
|
|
struct nf_conn *tmpl = info->ct;
|
|
|
int err;
|
|
|
|
|
@@ -506,11 +510,18 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
|
|
|
return -ENOENT;
|
|
|
|
|
|
ovs_ct_update_key(skb, info, key, true);
|
|
|
+ }
|
|
|
|
|
|
- if (ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
|
|
|
- WARN_ONCE(1, "helper rejected packet");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ /* Call the helper only if:
|
|
|
+ * - nf_conntrack_in() was executed above ("!cached") for a confirmed
|
|
|
+ * connection, or
|
|
|
+ * - When committing an unconfirmed connection.
|
|
|
+ */
|
|
|
+ ct = nf_ct_get(skb, &ctinfo);
|
|
|
+ if (ct && (nf_ct_is_confirmed(ct) ? !cached : info->commit) &&
|
|
|
+ ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
|
|
|
+ WARN_ONCE(1, "helper rejected packet");
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
return 0;
|