aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/conntrack.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch/conntrack.c')
-rw-r--r--net/openvswitch/conntrack.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 08679ebb3068..e3c4c6c3fef7 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -629,6 +629,34 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
629 return ct; 629 return ct;
630} 630}
631 631
632static
633struct nf_conn *ovs_ct_executed(struct net *net,
634 const struct sw_flow_key *key,
635 const struct ovs_conntrack_info *info,
636 struct sk_buff *skb,
637 bool *ct_executed)
638{
639 struct nf_conn *ct = NULL;
640
641 /* If no ct, check if we have evidence that an existing conntrack entry
642 * might be found for this skb. This happens when we lose a skb->_nfct
643 * due to an upcall, or if the direction is being forced. If the
644 * connection was not confirmed, it is not cached and needs to be run
645 * through conntrack again.
646 */
647 *ct_executed = (key->ct_state & OVS_CS_F_TRACKED) &&
648 !(key->ct_state & OVS_CS_F_INVALID) &&
649 (key->ct_zone == info->zone.id);
650
651 if (*ct_executed || (!key->ct_state && info->force)) {
652 ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
653 !!(key->ct_state &
654 OVS_CS_F_NAT_MASK));
655 }
656
657 return ct;
658}
659
632/* Determine whether skb->_nfct is equal to the result of conntrack lookup. */ 660/* Determine whether skb->_nfct is equal to the result of conntrack lookup. */
633static bool skb_nfct_cached(struct net *net, 661static bool skb_nfct_cached(struct net *net,
634 const struct sw_flow_key *key, 662 const struct sw_flow_key *key,
@@ -637,24 +665,17 @@ static bool skb_nfct_cached(struct net *net,
637{ 665{
638 enum ip_conntrack_info ctinfo; 666 enum ip_conntrack_info ctinfo;
639 struct nf_conn *ct; 667 struct nf_conn *ct;
668 bool ct_executed = true;
640 669
641 ct = nf_ct_get(skb, &ctinfo); 670 ct = nf_ct_get(skb, &ctinfo);
642 /* If no ct, check if we have evidence that an existing conntrack entry
643 * might be found for this skb. This happens when we lose a skb->_nfct
644 * due to an upcall. If the connection was not confirmed, it is not
645 * cached and needs to be run through conntrack again.
646 */
647 if (!ct && key->ct_state & OVS_CS_F_TRACKED &&
648 !(key->ct_state & OVS_CS_F_INVALID) &&
649 key->ct_zone == info->zone.id) {
650 ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
651 !!(key->ct_state
652 & OVS_CS_F_NAT_MASK));
653 if (ct)
654 nf_ct_get(skb, &ctinfo);
655 }
656 if (!ct) 671 if (!ct)
672 ct = ovs_ct_executed(net, key, info, skb, &ct_executed);
673
674 if (ct)
675 nf_ct_get(skb, &ctinfo);
676 else
657 return false; 677 return false;
678
658 if (!net_eq(net, read_pnet(&ct->ct_net))) 679 if (!net_eq(net, read_pnet(&ct->ct_net)))
659 return false; 680 return false;
660 if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct))) 681 if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct)))
@@ -679,7 +700,7 @@ static bool skb_nfct_cached(struct net *net,
679 return false; 700 return false;
680 } 701 }
681 702
682 return true; 703 return ct_executed;
683} 704}
684 705
685#ifdef CONFIG_NF_NAT_NEEDED 706#ifdef CONFIG_NF_NAT_NEEDED