On Sun, Mar 2, 2025 at 9:14 PM Jianbo Liu <jian...@nvidia.com> wrote:
>
>
>
> On 3/3/2025 2:22 AM, Xin Long wrote:
> > On Tue, Feb 25, 2025 at 9:57 AM Xin Long <lucien....@gmail.com> wrote:
> >>
> >> On Mon, Feb 24, 2025 at 8:38 PM Jianbo Liu <jian...@nvidia.com> wrote:
> >>>
> >>>
> >>>
> >>> On 2/25/2025 3:55 AM, Xin Long wrote:
> >>>> On Mon, Feb 24, 2025 at 4:01 AM Jianbo Liu <jian...@nvidia.com> wrote:
> >>>>>
> >>>>>
> >>>>>
> >>>>> On 8/13/2024 1:17 AM, Xin Long wrote:
> >>>>>> Similar to commit 70f06c115bcc ("sched: act_ct: switch to per-action
> >>>>>> label counting"), we should also switch to per-action label counting
> >>>>>> in openvswitch conntrack, as Florian suggested.
> >>>>>>
> >>>>>> The difference is that nf_connlabels_get() is called unconditionally
> >>>>>> when creating an ct action in ovs_ct_copy_action(). As with these
> >>>>>> flows:
> >>>>>>
> >>>>>>      table=0,ip,actions=ct(commit,table=1)
> >>>>>>      
> >>>>>> table=1,ip,actions=ct(commit,exec(set_field:0xac->ct_label),table=2)
> >>>>>>
> >>>>>> it needs to make sure the label ext is created in the 1st flow before
> >>>>>> the ct is committed in ovs_ct_commit(). Otherwise, the warning in
> >>>>>> nf_ct_ext_add() when creating the label ext in the 2nd flow will
> >>>>>> be triggered:
> >>>>>>
> >>>>>>       WARN_ON(nf_ct_is_confirmed(ct));
> >>>>>>
> >>>>>
> >>>>> Hi Xin Long,
> >>>>>
> >>>>> The ct can be committed before openvswitch handles packets with CT
> >>>>> actions. And we can trigger the warning by creating VF and running ping
> >>>>> over it with the following configurations:
> >>>>>
> >>>>> ovs-vsctl add-br br
> >>>>> ovs-vsctl add-port br eth2
> >>>>> ovs-vsctl add-port br eth4
> >>>>> ovs-ofctl add-flow br "table=0, in_port=eth4,ip,ct_state=-trk
> >>>>> actions=ct(table=1)"
> >>>>> ovs-ofctl add-flow br "table=1, in_port=eth4,ip,ct_state=+trk+new
> >>>>> actions=ct(exec(set_field:0xef7d->ct_label), commit), output:eth2"
> >>>>> ovs-ofctl add-flow br "table=1, in_port=eth4,ip,ct_label=0xef7d,
> >>>>> ct_state=+trk+est actions=output:eth2"
> >>>>>
> >>>>> The eth2 is PF, and eth4 is VF's representor.
> >>>>> Would you like to fix it?
> >>>> Hi, Jianbo,
> >>>>
> >>>> Sure, we have to attach a new ct to the skb in __ovs_ct_lookup() for
> >>>> this case, and even delete the one created before ovs_ct.
> >>>>
> >>>> Can you check if this works on your env?
> >>>
> >>> Yes, it works.
> >>> Could you please submit the formal patch? Thanks!
> >> Great, I will post after running some of my local tests.
> >>
> > Hi Jianbo,
> >
> > I recently ran some tests and observed that the current approach cannot
> > completely avoid the warning. If an skb enters __ovs_ct_lookup() without
> > an attached connection tracking (ct) entry, it may still acquire an
> > existing ct created outside of OVS (possibly by netfilter) through
> > nf_conntrack_in(). This will trigger the warning in ovs_ct_set_labels().
> >
> > Deleting a ct created outside OVS and creating a new one within
> > __ovs_ct_lookup() doesn't seem reasonable and would be difficult to
>
> Yes, I'm also skeptical of your temporary fix, and waiting for your
> formal one.
Cool.

>
> > implement. However, since OVS is not supposed to use ct entries created
> > externally, I believe ct zones can be used to prevent this issue.
> > In your case, the following flows should work:
> >
> > ovs-ofctl add-flow br "table=0, in_port=eth4,ip,ct_state=-trk
> > actions=ct(table=1,zone=1)"
> > ovs-ofctl add-flow br "table=1,
> > in_port=eth4,ip,ct_state=+trk+new,ct_zone=1
> > actions=ct(exec(set_field:0xef7d->ct_label),commit,zone=1),
> > output:eth2"
> > ovs-ofctl add-flow br "table=1,
> > in_port=eth4,ip,ct_label=0xef7d,ct_state=+trk+est,ct_zone=1
> > actions=output:eth2"
> >
> > Regarding the warning triggered by externally created ct entries, I plan
> > to remove the ovs_ct_get_conn_labels() call from ovs_ct_set_labels() and
> > I'll let nf_connlabels_replace() return an error in such cases, similar
> > to how tcf_ct_act_set_labels() handles this scenario in tc act_ct.
> >
>
> It's a good idea to be consistent with act_ct implementation. But, would
> you like to revert first if it takes long time to work on the fix?
Sorry, revert which one?
If you mean the fix in skb_nfct_cached(), it hasn't been posted and
will not be posted.

Thanks.
>
> Thanks!
>
> > Thanks.
> >>>
> >>>>
> >>>> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> >>>> index 3bb4810234aa..c599ee013dfe 100644
> >>>> --- a/net/openvswitch/conntrack.c
> >>>> +++ b/net/openvswitch/conntrack.c
> >>>> @@ -595,6 +595,11 @@ static bool skb_nfct_cached(struct net *net,
> >>>>                rcu_dereference(timeout_ext->timeout))
> >>>>                return false;
> >>>>        }
> >>>> +    if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && 
> >>>> !nf_ct_labels_find(ct)) {
> >>>> +        if (nf_ct_is_confirmed(ct))
> >>>> +            nf_ct_delete(ct, 0, 0);
> >>>> +        return false;
> >>>> +    }
> >>>>
> >>>> Thanks.
> >>>>
> >>>>>
> >>>>> Thanks!
> >>>>> Jianbo
> >>>>>
> >>>>>> Signed-off-by: Xin Long <lucien....@gmail.com>
> >>>>>> ---
> >>>>>> v2: move ovs_net into #if in ovs_ct_exit() as Jakub noticed.
> >>>>>> ---
> >>>>>>     net/openvswitch/conntrack.c | 30 ++++++++++++------------------
> >>>>>>     net/openvswitch/datapath.h  |  3 ---
> >>>>>>     2 files changed, 12 insertions(+), 21 deletions(-)
> >>>>>>
> >>>>>> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> >>>>>> index 8eb1d644b741..a3da5ee34f92 100644
> >>>>>> --- a/net/openvswitch/conntrack.c
> >>>>>> +++ b/net/openvswitch/conntrack.c
> >>>>>> @@ -1368,11 +1368,8 @@ bool ovs_ct_verify(struct net *net, enum 
> >>>>>> ovs_key_attr attr)
> >>>>>>             attr == OVS_KEY_ATTR_CT_MARK)
> >>>>>>                 return true;
> >>>>>>         if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
> >>>>>> -         attr == OVS_KEY_ATTR_CT_LABELS) {
> >>>>>> -             struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
> >>>>>> -
> >>>>>> -             return ovs_net->xt_label;
> >>>>>> -     }
> >>>>>> +         attr == OVS_KEY_ATTR_CT_LABELS)
> >>>>>> +             return true;
> >>>>>>
> >>>>>>         return false;
> >>>>>>     }
> >>>>>> @@ -1381,6 +1378,7 @@ int ovs_ct_copy_action(struct net *net, const 
> >>>>>> struct nlattr *attr,
> >>>>>>                        const struct sw_flow_key *key,
> >>>>>>                        struct sw_flow_actions **sfa,  bool log)
> >>>>>>     {
> >>>>>> +     unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * 
> >>>>>> BITS_PER_BYTE;
> >>>>>>         struct ovs_conntrack_info ct_info;
> >>>>>>         const char *helper = NULL;
> >>>>>>         u16 family;
> >>>>>> @@ -1409,6 +1407,12 @@ int ovs_ct_copy_action(struct net *net, const 
> >>>>>> struct nlattr *attr,
> >>>>>>                 return -ENOMEM;
> >>>>>>         }
> >>>>>>
> >>>>>> +     if (nf_connlabels_get(net, n_bits - 1)) {
> >>>>>> +             nf_ct_tmpl_free(ct_info.ct);
> >>>>>> +             OVS_NLERR(log, "Failed to set connlabel length");
> >>>>>> +             return -EOPNOTSUPP;
> >>>>>> +     }
> >>>>>> +
> >>>>>>         if (ct_info.timeout[0]) {
> >>>>>>                 if (nf_ct_set_timeout(net, ct_info.ct, family, 
> >>>>>> key->ip.proto,
> >>>>>>                                       ct_info.timeout))
> >>>>>> @@ -1577,6 +1581,7 @@ static void __ovs_ct_free_action(struct 
> >>>>>> ovs_conntrack_info *ct_info)
> >>>>>>         if (ct_info->ct) {
> >>>>>>                 if (ct_info->timeout[0])
> >>>>>>                         nf_ct_destroy_timeout(ct_info->ct);
> >>>>>> +             nf_connlabels_put(nf_ct_net(ct_info->ct));
> >>>>>>                 nf_ct_tmpl_free(ct_info->ct);
> >>>>>>         }
> >>>>>>     }
> >>>>>> @@ -2002,17 +2007,9 @@ struct genl_family dp_ct_limit_genl_family 
> >>>>>> __ro_after_init = {
> >>>>>>
> >>>>>>     int ovs_ct_init(struct net *net)
> >>>>>>     {
> >>>>>> -     unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * 
> >>>>>> BITS_PER_BYTE;
> >>>>>> +#if  IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
> >>>>>>         struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
> >>>>>>
> >>>>>> -     if (nf_connlabels_get(net, n_bits - 1)) {
> >>>>>> -             ovs_net->xt_label = false;
> >>>>>> -             OVS_NLERR(true, "Failed to set connlabel length");
> >>>>>> -     } else {
> >>>>>> -             ovs_net->xt_label = true;
> >>>>>> -     }
> >>>>>> -
> >>>>>> -#if  IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
> >>>>>>         return ovs_ct_limit_init(net, ovs_net);
> >>>>>>     #else
> >>>>>>         return 0;
> >>>>>> @@ -2021,12 +2018,9 @@ int ovs_ct_init(struct net *net)
> >>>>>>
> >>>>>>     void ovs_ct_exit(struct net *net)
> >>>>>>     {
> >>>>>> +#if  IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
> >>>>>>         struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
> >>>>>>
> >>>>>> -#if  IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
> >>>>>>         ovs_ct_limit_exit(net, ovs_net);
> >>>>>>     #endif
> >>>>>> -
> >>>>>> -     if (ovs_net->xt_label)
> >>>>>> -             nf_connlabels_put(net);
> >>>>>>     }
> >>>>>> diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
> >>>>>> index 9ca6231ea647..365b9bb7f546 100644
> >>>>>> --- a/net/openvswitch/datapath.h
> >>>>>> +++ b/net/openvswitch/datapath.h
> >>>>>> @@ -160,9 +160,6 @@ struct ovs_net {
> >>>>>>     #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
> >>>>>>         struct ovs_ct_limit_info *ct_limit_info;
> >>>>>>     #endif
> >>>>>> -
> >>>>>> -     /* Module reference for configuring conntrack. */
> >>>>>> -     bool xt_label;
> >>>>>>     };
> >>>>>>
> >>>>>>     /**
> >>>>>
> >>>
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to