Re: [ovs-dev] [PATCH net-next 3/3] net: sched: add helper support in act_ct

2022-10-06 Thread Xin Long
On Thu, Oct 6, 2022 at 10:11 AM Pablo Neira Ayuso  wrote:
>
> On Tue, Oct 04, 2022 at 09:19:56PM -0400, Xin Long wrote:
> [...]
> > @@ -1119,6 +1135,22 @@ static int tcf_ct_act(struct sk_buff *skb, const 
> > struct tc_action *a,
> >   if (err != NF_ACCEPT)
> >   goto drop;
> >
> > + if (commit && p->helper && !nfct_help(ct)) {
> > + err = __nf_ct_try_assign_helper(ct, p->tmpl, GFP_ATOMIC);
> > + if (err)
> > + goto drop;
> > + add_helper = true;
> > + if (p->ct_action & TCA_CT_ACT_NAT && !nfct_seqadj(ct)) {
> > + if (!nfct_seqadj_ext_add(ct))
>
> You can only add ct extensions if ct is !nf_ct_is_confirmed(ct)), is
> this guaranteed in this codepath?
This is a good catch, the same issue exists on __nf_ct_try_assign_helper(),
and also in __ovs_ct_lookup().

I could trigger the warning on OVS conntrack with the flow:

table=0, in_port=veth1,tcp,tcp_dst=2121,ct_state=-trk
actions=ct(commit, table=1)
table=1, in_port=veth1,tcp,tcp_dst=2121,ct_state=+trk+new
actions=ct(commit, alg=ftp),normal

I will prepare a fix for ovs conntrack first.

Thanks.

>
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + if (nf_ct_is_confirmed(ct) ? ((!cached && !skip_add) || add_helper) : 
> > commit) {
> > + if (nf_ct_helper(skb, family) != NF_ACCEPT)
> > + goto drop;
> > + }
> > +
> >   if (commit) {
> >   tcf_ct_act_set_mark(ct, p->mark, p->mark_mask);
> >   tcf_ct_act_set_labels(ct, p->labels, p->labels_mask);
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH net-next 3/3] net: sched: add helper support in act_ct

2022-10-06 Thread Pablo Neira Ayuso
On Tue, Oct 04, 2022 at 09:19:56PM -0400, Xin Long wrote:
[...]
> @@ -1119,6 +1135,22 @@ static int tcf_ct_act(struct sk_buff *skb, const 
> struct tc_action *a,
>   if (err != NF_ACCEPT)
>   goto drop;
>  
> + if (commit && p->helper && !nfct_help(ct)) {
> + err = __nf_ct_try_assign_helper(ct, p->tmpl, GFP_ATOMIC);
> + if (err)
> + goto drop;
> + add_helper = true;
> + if (p->ct_action & TCA_CT_ACT_NAT && !nfct_seqadj(ct)) {
> + if (!nfct_seqadj_ext_add(ct))

You can only add ct extensions if ct is !nf_ct_is_confirmed(ct)), is
this guaranteed in this codepath?

> + return -EINVAL;
> + }
> + }
> +
> + if (nf_ct_is_confirmed(ct) ? ((!cached && !skip_add) || add_helper) : 
> commit) {
> + if (nf_ct_helper(skb, family) != NF_ACCEPT)
> + goto drop;
> + }
> +
>   if (commit) {
>   tcf_ct_act_set_mark(ct, p->mark, p->mark_mask);
>   tcf_ct_act_set_labels(ct, p->labels, p->labels_mask);
___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Re: [ovs-dev] [PATCH net-next 3/3] net: sched: add helper support in act_ct

2022-10-06 Thread Xin Long
On Thu, Oct 6, 2022 at 5:57 AM Paolo Abeni  wrote:
>
> On Tue, 2022-10-04 at 21:19 -0400, Xin Long wrote:
> > This patch is to add helper support in act_ct for OVS actions=ct(alg=xxx)
> > offloading, which is corresponding to Commit cae3a2627520 ("openvswitch:
> > Allow attaching helpers to ct action") in OVS kernel part.
> >
> > The difference is when adding TC actions family and proto cannot be got
> > from the filter/match, other than helper name in tb[TCA_CT_HELPER_NAME],
> > we also need to send the family in tb[TCA_CT_HELPER_FAMILY] and the
> > proto in tb[TCA_CT_HELPER_PROTO] to kernel.
> >
> > Signed-off-by: Xin Long 
> > ---
> >  include/net/tc_act/tc_ct.h|   1 +
> >  include/uapi/linux/tc_act/tc_ct.h |   3 +
> >  net/sched/act_ct.c| 113 --
> >  3 files changed, 112 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/net/tc_act/tc_ct.h b/include/net/tc_act/tc_ct.h
> > index 8250d6f0a462..b24ea2d9400b 100644
> > --- a/include/net/tc_act/tc_ct.h
> > +++ b/include/net/tc_act/tc_ct.h
> > @@ -10,6 +10,7 @@
> >  #include 
> >
> >  struct tcf_ct_params {
> > + struct nf_conntrack_helper *helper;
> >   struct nf_conn *tmpl;
> >   u16 zone;
> >
> > diff --git a/include/uapi/linux/tc_act/tc_ct.h 
> > b/include/uapi/linux/tc_act/tc_ct.h
> > index 5fb1d7ac1027..6c5200f0ed38 100644
> > --- a/include/uapi/linux/tc_act/tc_ct.h
> > +++ b/include/uapi/linux/tc_act/tc_ct.h
> > @@ -22,6 +22,9 @@ enum {
> >   TCA_CT_NAT_PORT_MIN,/* be16 */
> >   TCA_CT_NAT_PORT_MAX,/* be16 */
> >   TCA_CT_PAD,
> > + TCA_CT_HELPER_NAME, /* string */
> > + TCA_CT_HELPER_FAMILY,   /* u8 */
> > + TCA_CT_HELPER_PROTO,/* u8 */
> >   __TCA_CT_MAX
> >  };
> >
> > diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> > index 193a460a9d7f..f237c27079db 100644
> > --- a/net/sched/act_ct.c
> > +++ b/net/sched/act_ct.c
> > @@ -33,6 +33,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >
> >  static struct workqueue_struct *act_ct_wq;
> > @@ -655,7 +656,7 @@ struct tc_ct_action_net {
> >
> >  /* Determine whether skb->_nfct is equal to the result of conntrack 
> > lookup. */
> >  static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb,
> > -u16 zone_id, bool force)
> > +struct tcf_ct_params *p, bool force)
> >  {
> >   enum ip_conntrack_info ctinfo;
> >   struct nf_conn *ct;
> > @@ -665,8 +666,15 @@ static bool tcf_ct_skb_nfct_cached(struct net *net, 
> > struct sk_buff *skb,
> >   return false;
> >   if (!net_eq(net, read_pnet(>ct_net)))
> >   goto drop_ct;
> > - if (nf_ct_zone(ct)->id != zone_id)
> > + if (nf_ct_zone(ct)->id != p->zone)
> >   goto drop_ct;
> > + if (p->helper) {
> > + struct nf_conn_help *help;
> > +
> > + help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
> > + if (help && rcu_access_pointer(help->helper) != p->helper)
> > + goto drop_ct;
> > + }
> >
> >   /* Force conntrack entry direction. */
> >   if (force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
> > @@ -832,6 +840,13 @@ static int tcf_ct_handle_fragments(struct net *net, 
> > struct sk_buff *skb,
> >
> >  static void tcf_ct_params_free(struct tcf_ct_params *params)
> >  {
> > + if (params->helper) {
> > +#if IS_ENABLED(CONFIG_NF_NAT)
> > + if (params->ct_action & TCA_CT_ACT_NAT)
> > + nf_nat_helper_put(params->helper);
> > +#endif
> > + nf_conntrack_helper_put(params->helper);
> > + }
>
> There is exactly the same code chunk in __ovs_ct_free_action(), I guess
> you can extract a common helper here, too.
>
> >   if (params->ct_ft)
> >   tcf_ct_flow_table_put(params->ct_ft);
> >   if (params->tmpl)
> > @@ -1033,6 +1048,7 @@ static int tcf_ct_act(struct sk_buff *skb, const 
> > struct tc_action *a,
> >   struct nf_hook_state state;
> >   int nh_ofs, err, retval;
> >   struct tcf_ct_params *p;
> > + bool add_helper = false;
> >   bool skip_add = false;
> >   bool defrag = false;
> >   struct nf_conn *ct;
> > @@ -1086,7 +1102,7 @@ static int tcf_ct_act(struct sk_buff *skb, const 
> > struct tc_action *a,
> >* actually run the packet through conntrack twice unless it's for a
> >* different zone.
> >*/
> > - cached = tcf_ct_skb_nfct_cached(net, skb, p->zone, force);
> > + cached = tcf_ct_skb_nfct_cached(net, skb, p, force);
> >   if (!cached) {
> >   if (tcf_ct_flow_table_lookup(p, skb, family)) {
> >   skip_add = true;
> > @@ -1119,6 +1135,22 @@ static int tcf_ct_act(struct sk_buff *skb, const 
> > struct tc_action *a,
> >   if (err != NF_ACCEPT)
> >   goto drop;
> >
> > + if (commit && p->helper && !nfct_help(ct)) {
> > + err = 

Re: [ovs-dev] [PATCH net-next 3/3] net: sched: add helper support in act_ct

2022-10-06 Thread Paolo Abeni
On Tue, 2022-10-04 at 21:19 -0400, Xin Long wrote:
> This patch is to add helper support in act_ct for OVS actions=ct(alg=xxx)
> offloading, which is corresponding to Commit cae3a2627520 ("openvswitch:
> Allow attaching helpers to ct action") in OVS kernel part.
> 
> The difference is when adding TC actions family and proto cannot be got
> from the filter/match, other than helper name in tb[TCA_CT_HELPER_NAME],
> we also need to send the family in tb[TCA_CT_HELPER_FAMILY] and the
> proto in tb[TCA_CT_HELPER_PROTO] to kernel.
> 
> Signed-off-by: Xin Long 
> ---
>  include/net/tc_act/tc_ct.h|   1 +
>  include/uapi/linux/tc_act/tc_ct.h |   3 +
>  net/sched/act_ct.c| 113 --
>  3 files changed, 112 insertions(+), 5 deletions(-)
> 
> diff --git a/include/net/tc_act/tc_ct.h b/include/net/tc_act/tc_ct.h
> index 8250d6f0a462..b24ea2d9400b 100644
> --- a/include/net/tc_act/tc_ct.h
> +++ b/include/net/tc_act/tc_ct.h
> @@ -10,6 +10,7 @@
>  #include 
>  
>  struct tcf_ct_params {
> + struct nf_conntrack_helper *helper;
>   struct nf_conn *tmpl;
>   u16 zone;
>  
> diff --git a/include/uapi/linux/tc_act/tc_ct.h 
> b/include/uapi/linux/tc_act/tc_ct.h
> index 5fb1d7ac1027..6c5200f0ed38 100644
> --- a/include/uapi/linux/tc_act/tc_ct.h
> +++ b/include/uapi/linux/tc_act/tc_ct.h
> @@ -22,6 +22,9 @@ enum {
>   TCA_CT_NAT_PORT_MIN,/* be16 */
>   TCA_CT_NAT_PORT_MAX,/* be16 */
>   TCA_CT_PAD,
> + TCA_CT_HELPER_NAME, /* string */
> + TCA_CT_HELPER_FAMILY,   /* u8 */
> + TCA_CT_HELPER_PROTO,/* u8 */
>   __TCA_CT_MAX
>  };
>  
> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> index 193a460a9d7f..f237c27079db 100644
> --- a/net/sched/act_ct.c
> +++ b/net/sched/act_ct.c
> @@ -33,6 +33,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  static struct workqueue_struct *act_ct_wq;
> @@ -655,7 +656,7 @@ struct tc_ct_action_net {
>  
>  /* Determine whether skb->_nfct is equal to the result of conntrack lookup. 
> */
>  static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb,
> -u16 zone_id, bool force)
> +struct tcf_ct_params *p, bool force)
>  {
>   enum ip_conntrack_info ctinfo;
>   struct nf_conn *ct;
> @@ -665,8 +666,15 @@ static bool tcf_ct_skb_nfct_cached(struct net *net, 
> struct sk_buff *skb,
>   return false;
>   if (!net_eq(net, read_pnet(>ct_net)))
>   goto drop_ct;
> - if (nf_ct_zone(ct)->id != zone_id)
> + if (nf_ct_zone(ct)->id != p->zone)
>   goto drop_ct;
> + if (p->helper) {
> + struct nf_conn_help *help;
> +
> + help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
> + if (help && rcu_access_pointer(help->helper) != p->helper)
> + goto drop_ct;
> + }
>  
>   /* Force conntrack entry direction. */
>   if (force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
> @@ -832,6 +840,13 @@ static int tcf_ct_handle_fragments(struct net *net, 
> struct sk_buff *skb,
>  
>  static void tcf_ct_params_free(struct tcf_ct_params *params)
>  {
> + if (params->helper) {
> +#if IS_ENABLED(CONFIG_NF_NAT)
> + if (params->ct_action & TCA_CT_ACT_NAT)
> + nf_nat_helper_put(params->helper);
> +#endif
> + nf_conntrack_helper_put(params->helper);
> + }

There is exactly the same code chunk in __ovs_ct_free_action(), I guess
you can extract a common helper here, too.

>   if (params->ct_ft)
>   tcf_ct_flow_table_put(params->ct_ft);
>   if (params->tmpl)
> @@ -1033,6 +1048,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct 
> tc_action *a,
>   struct nf_hook_state state;
>   int nh_ofs, err, retval;
>   struct tcf_ct_params *p;
> + bool add_helper = false;
>   bool skip_add = false;
>   bool defrag = false;
>   struct nf_conn *ct;
> @@ -1086,7 +1102,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct 
> tc_action *a,
>* actually run the packet through conntrack twice unless it's for a
>* different zone.
>*/
> - cached = tcf_ct_skb_nfct_cached(net, skb, p->zone, force);
> + cached = tcf_ct_skb_nfct_cached(net, skb, p, force);
>   if (!cached) {
>   if (tcf_ct_flow_table_lookup(p, skb, family)) {
>   skip_add = true;
> @@ -1119,6 +1135,22 @@ static int tcf_ct_act(struct sk_buff *skb, const 
> struct tc_action *a,
>   if (err != NF_ACCEPT)
>   goto drop;
>  
> + if (commit && p->helper && !nfct_help(ct)) {
> + err = __nf_ct_try_assign_helper(ct, p->tmpl, GFP_ATOMIC);
> + if (err)
> + goto drop;
> + add_helper = true;
> + if (p->ct_action & TCA_CT_ACT_NAT && !nfct_seqadj(ct)) {
> + if (!nfct_seqadj_ext_add(ct))
> + 

[ovs-dev] [PATCH net-next 3/3] net: sched: add helper support in act_ct

2022-10-05 Thread Xin Long
This patch is to add helper support in act_ct for OVS actions=ct(alg=xxx)
offloading, which is corresponding to Commit cae3a2627520 ("openvswitch:
Allow attaching helpers to ct action") in OVS kernel part.

The difference is when adding TC actions family and proto cannot be got
from the filter/match, other than helper name in tb[TCA_CT_HELPER_NAME],
we also need to send the family in tb[TCA_CT_HELPER_FAMILY] and the
proto in tb[TCA_CT_HELPER_PROTO] to kernel.

Signed-off-by: Xin Long 
---
 include/net/tc_act/tc_ct.h|   1 +
 include/uapi/linux/tc_act/tc_ct.h |   3 +
 net/sched/act_ct.c| 113 --
 3 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/include/net/tc_act/tc_ct.h b/include/net/tc_act/tc_ct.h
index 8250d6f0a462..b24ea2d9400b 100644
--- a/include/net/tc_act/tc_ct.h
+++ b/include/net/tc_act/tc_ct.h
@@ -10,6 +10,7 @@
 #include 
 
 struct tcf_ct_params {
+   struct nf_conntrack_helper *helper;
struct nf_conn *tmpl;
u16 zone;
 
diff --git a/include/uapi/linux/tc_act/tc_ct.h 
b/include/uapi/linux/tc_act/tc_ct.h
index 5fb1d7ac1027..6c5200f0ed38 100644
--- a/include/uapi/linux/tc_act/tc_ct.h
+++ b/include/uapi/linux/tc_act/tc_ct.h
@@ -22,6 +22,9 @@ enum {
TCA_CT_NAT_PORT_MIN,/* be16 */
TCA_CT_NAT_PORT_MAX,/* be16 */
TCA_CT_PAD,
+   TCA_CT_HELPER_NAME, /* string */
+   TCA_CT_HELPER_FAMILY,   /* u8 */
+   TCA_CT_HELPER_PROTO,/* u8 */
__TCA_CT_MAX
 };
 
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index 193a460a9d7f..f237c27079db 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -33,6 +33,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static struct workqueue_struct *act_ct_wq;
@@ -655,7 +656,7 @@ struct tc_ct_action_net {
 
 /* Determine whether skb->_nfct is equal to the result of conntrack lookup. */
 static bool tcf_ct_skb_nfct_cached(struct net *net, struct sk_buff *skb,
-  u16 zone_id, bool force)
+  struct tcf_ct_params *p, bool force)
 {
enum ip_conntrack_info ctinfo;
struct nf_conn *ct;
@@ -665,8 +666,15 @@ static bool tcf_ct_skb_nfct_cached(struct net *net, struct 
sk_buff *skb,
return false;
if (!net_eq(net, read_pnet(>ct_net)))
goto drop_ct;
-   if (nf_ct_zone(ct)->id != zone_id)
+   if (nf_ct_zone(ct)->id != p->zone)
goto drop_ct;
+   if (p->helper) {
+   struct nf_conn_help *help;
+
+   help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+   if (help && rcu_access_pointer(help->helper) != p->helper)
+   goto drop_ct;
+   }
 
/* Force conntrack entry direction. */
if (force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
@@ -832,6 +840,13 @@ static int tcf_ct_handle_fragments(struct net *net, struct 
sk_buff *skb,
 
 static void tcf_ct_params_free(struct tcf_ct_params *params)
 {
+   if (params->helper) {
+#if IS_ENABLED(CONFIG_NF_NAT)
+   if (params->ct_action & TCA_CT_ACT_NAT)
+   nf_nat_helper_put(params->helper);
+#endif
+   nf_conntrack_helper_put(params->helper);
+   }
if (params->ct_ft)
tcf_ct_flow_table_put(params->ct_ft);
if (params->tmpl)
@@ -1033,6 +1048,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct 
tc_action *a,
struct nf_hook_state state;
int nh_ofs, err, retval;
struct tcf_ct_params *p;
+   bool add_helper = false;
bool skip_add = false;
bool defrag = false;
struct nf_conn *ct;
@@ -1086,7 +1102,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct 
tc_action *a,
 * actually run the packet through conntrack twice unless it's for a
 * different zone.
 */
-   cached = tcf_ct_skb_nfct_cached(net, skb, p->zone, force);
+   cached = tcf_ct_skb_nfct_cached(net, skb, p, force);
if (!cached) {
if (tcf_ct_flow_table_lookup(p, skb, family)) {
skip_add = true;
@@ -1119,6 +1135,22 @@ static int tcf_ct_act(struct sk_buff *skb, const struct 
tc_action *a,
if (err != NF_ACCEPT)
goto drop;
 
+   if (commit && p->helper && !nfct_help(ct)) {
+   err = __nf_ct_try_assign_helper(ct, p->tmpl, GFP_ATOMIC);
+   if (err)
+   goto drop;
+   add_helper = true;
+   if (p->ct_action & TCA_CT_ACT_NAT && !nfct_seqadj(ct)) {
+   if (!nfct_seqadj_ext_add(ct))
+   return -EINVAL;
+   }
+   }
+
+   if (nf_ct_is_confirmed(ct) ? ((!cached && !skip_add) || add_helper) : 
commit) {
+   if (nf_ct_helper(skb, family) != NF_ACCEPT)
+   goto drop;
+   }
+
if (commit) {