/* 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) { u8 state; int err; state = key->ct.state; if (key->ct.zone == info->zone.id && ((state & OVS_CS_F_TRACKED) && !(state & OVS_CS_F_NEW))) { /* Previous lookup has shown that this connection is already * tracked and committed. Skip committing. */ return 0; } err = __ovs_ct_lookup(net, key, info, skb); if (err) return err; if (nf_conntrack_confirm(skb) != NF_ACCEPT) return -EINVAL; ovs_ct_update_key(skb, key, true); return 0; }
/* Lookup connection and read fields into key. */ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key, const struct ovs_conntrack_info *info, struct sk_buff *skb) { struct nf_conntrack_expect *exp; exp = ovs_ct_expect_find(net, &info->zone, info->family, skb); if (exp) { u8 state; state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED; __ovs_ct_update_key(key, state, &info->zone, exp->master); } else { int err; err = __ovs_ct_lookup(net, key, info, skb); if (err) return err; } return 0; }