Re: [PATCH net-next] seg6: fool-proof the processing of SRv6 behavior attributes

2021-02-03 Thread David Ahern
On 2/3/21 7:27 PM, Andrea Mayer wrote:
> 
> I think there is an issue here because BITS_PER_TYPE(unsigned long) is greater
> than the SEG6_LOCAL_MAX (currently = 9).
> 
> I think it should be like this:
> 
>  BUILD_BUG_ON(SEG6_LOCAL_MAX + 1 > BITS_PER_TYPE(unsigned long))
> 
> I will send a v2 with the changes discussed so far.

yes, I had that backwards.




Re: [PATCH net-next] seg6: fool-proof the processing of SRv6 behavior attributes

2021-02-03 Thread Andrea Mayer
Hi David,
thanks for your time.

On Wed, 3 Feb 2021 08:59:40 -0700
David Ahern  wrote:

> On 2/2/21 11:56 AM, Andrea Mayer wrote:
> > diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
> > index b07f7c1c82a4..7cc50d506902 100644
> > --- a/net/ipv6/seg6_local.c
> > +++ b/net/ipv6/seg6_local.c
> > @@ -31,6 +31,9 @@
> >  #include 
> >  #include 
> >  
> > +#define SEG6_F_ATTR(i) BIT(i)
> > +#define SEG6_LOCAL_MAX_SUPP32
> > +
> 
> SEG6_LOCAL_MAX_SUPP should not be needed; it can be derived from the type:
> 

Yes, we can avoid the SEG6_LOCAL_MAX_SUPP. Using the BITS_PER_TYPE macro seems
better to me and it avoids nailing the value 32 as the limit. At compile time,
the kernel build will fail if the total number of SRv6 attributes will exceed
the number of bits available in the unsigned long bitmap (whatever is the
reference architecture). Therefore, I'm going to follow your suggestion!

> BUILD_BUG_ON(BITS_PER_TYPE(unsigned long) > SEG6_LOCAL_MAX)
> 

I think there is an issue here because BITS_PER_TYPE(unsigned long) is greater
than the SEG6_LOCAL_MAX (currently = 9).

I think it should be like this:

 BUILD_BUG_ON(SEG6_LOCAL_MAX + 1 > BITS_PER_TYPE(unsigned long))

I will send a v2 with the changes discussed so far.

Thank you,
Andrea


Re: [PATCH net-next] seg6: fool-proof the processing of SRv6 behavior attributes

2021-02-03 Thread David Ahern
On 2/2/21 11:56 AM, Andrea Mayer wrote:
> diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
> index b07f7c1c82a4..7cc50d506902 100644
> --- a/net/ipv6/seg6_local.c
> +++ b/net/ipv6/seg6_local.c
> @@ -31,6 +31,9 @@
>  #include 
>  #include 
>  
> +#define SEG6_F_ATTR(i)   BIT(i)
> +#define SEG6_LOCAL_MAX_SUPP  32
> +

SEG6_LOCAL_MAX_SUPP should not be needed; it can be derived from the type:

BUILD_BUG_ON(BITS_PER_TYPE(unsigned long) > SEG6_LOCAL_MAX)

The use of BIT() looks fine.


[PATCH net-next] seg6: fool-proof the processing of SRv6 behavior attributes

2021-02-02 Thread Andrea Mayer
The set of required attributes for a given SRv6 behavior is identified
using a bitmap stored in an unsigned long, since the initial design of SRv6
networking in Linux. Recently the same approach has been used for
identifying the optional attributes.

However, the number of attributes supported by SRv6 behaviors depends on
the size of the unsigned long type which changes with the architecture.
Indeed, on a 64-bit architecture, an SRv6 behavior can support up to 64
attributes while on a 32-bit architecture it can support at most 32
attributes.

To fool-proof the processing of SRv6 behaviors we will support at most 32
attributes independently from the reference architecture.

Consequently, this patch aims to:

 - verify, at compile time, that the total number of attributes does not
   exceed the fixed value of 32. Otherwise, kernel build fails forcing
   developers to reconsider adding a new attribute or extend the total
   number of supported attributes by the SRv6 behaviors.

 - replace all patterns (1 << i) with the macro SEG6_F_ATTR(i) in order to
   address potential overflow issues caused by 32-bit signed arithmetic.

Thanks to Colin Ian King for catching the overflow problem, providing a
solution and inspiring this patch.
Thanks to Jakub Kicinski for his useful suggestions during the design of
this patch.

Signed-off-by: Andrea Mayer 
---
 net/ipv6/seg6_local.c | 68 +--
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index b07f7c1c82a4..7cc50d506902 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -31,6 +31,9 @@
 #include 
 #include 
 
+#define SEG6_F_ATTR(i) BIT(i)
+#define SEG6_LOCAL_MAX_SUPP32
+
 struct seg6_local_lwt;
 
 /* callbacks used for customizing the creation and destruction of a behavior */
@@ -660,8 +663,8 @@ seg6_end_dt_mode seg6_end_dt6_parse_mode(struct 
seg6_local_lwt *slwt)
unsigned long parsed_optattrs = slwt->parsed_optattrs;
bool legacy, vrfmode;
 
-   legacy  = !!(parsed_optattrs & (1 << SEG6_LOCAL_TABLE));
-   vrfmode = !!(parsed_optattrs & (1 << SEG6_LOCAL_VRFTABLE));
+   legacy  = !!(parsed_optattrs & SEG6_F_ATTR(SEG6_LOCAL_TABLE));
+   vrfmode = !!(parsed_optattrs & SEG6_F_ATTR(SEG6_LOCAL_VRFTABLE));
 
if (!(legacy ^ vrfmode))
/* both are absent or present: invalid DT6 mode */
@@ -883,32 +886,32 @@ static struct seg6_action_desc seg6_action_table[] = {
},
{
.action = SEG6_LOCAL_ACTION_END_X,
-   .attrs  = (1 << SEG6_LOCAL_NH6),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_NH6),
.input  = input_action_end_x,
},
{
.action = SEG6_LOCAL_ACTION_END_T,
-   .attrs  = (1 << SEG6_LOCAL_TABLE),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_TABLE),
.input  = input_action_end_t,
},
{
.action = SEG6_LOCAL_ACTION_END_DX2,
-   .attrs  = (1 << SEG6_LOCAL_OIF),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_OIF),
.input  = input_action_end_dx2,
},
{
.action = SEG6_LOCAL_ACTION_END_DX6,
-   .attrs  = (1 << SEG6_LOCAL_NH6),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_NH6),
.input  = input_action_end_dx6,
},
{
.action = SEG6_LOCAL_ACTION_END_DX4,
-   .attrs  = (1 << SEG6_LOCAL_NH4),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_NH4),
.input  = input_action_end_dx4,
},
{
.action = SEG6_LOCAL_ACTION_END_DT4,
-   .attrs  = (1 << SEG6_LOCAL_VRFTABLE),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_VRFTABLE),
 #ifdef CONFIG_NET_L3_MASTER_DEV
.input  = input_action_end_dt4,
.slwt_ops   = {
@@ -920,30 +923,30 @@ static struct seg6_action_desc seg6_action_table[] = {
.action = SEG6_LOCAL_ACTION_END_DT6,
 #ifdef CONFIG_NET_L3_MASTER_DEV
.attrs  = 0,
-   .optattrs   = (1 << SEG6_LOCAL_TABLE) |
- (1 << SEG6_LOCAL_VRFTABLE),
+   .optattrs   = SEG6_F_ATTR(SEG6_LOCAL_TABLE) |
+ SEG6_F_ATTR(SEG6_LOCAL_VRFTABLE),
.slwt_ops   = {
.build_state = seg6_end_dt6_build,
  },
 #else
-   .attrs  = (1 << SEG6_LOCAL_TABLE),
+   .attrs  = SEG6_F_ATTR(SEG6_LOCAL_TABLE),
 #endif
.input  = input_action_end_dt6,
},
{
.action =