* 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;
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;