Re: [PATCH v8 3/7] can: set CANFD_FDF flag in all CAN FD frame structures

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun. 11 Sept. 2022 at 21:23, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
> On 11.09.22 09:51, Vincent Mailhol wrote:
> > On Tue. 2 Aug. 2022 at 04:02, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
> >> To simplify the testing in user space all struct canfd_frame's provided by
> >> the CAN subsystem of the Linux kernel now have the CANFD_FDF flag set in
> >> canfd_frame::flags.
> >>
> >> NB: Handcrafted ETH_P_CANFD frames introduced via PF_PACKET socket might
> >> not set this bit correctly. During the check for sufficient headroom in
> >> PF_PACKET sk_buffs the uninitialized CAN sk_buff data structures are filled.
> >> In the case of a CAN FD frame the CANFD_FDF flag is set accordingly.
> >>
> >> As the CAN frame content is already zero initialized in alloc_canfd_skb()
> >> the obsolete initialization of cf->flags in the CTU CAN FD driver has been
> >> removed as it would overwrite the already set CANFD_FDF flag.
> >>
> >> Signed-off-by: Oliver Hartkopp <socketcan@xxxxxxxxxxxx>
> >> ---
> >>   drivers/net/can/ctucanfd/ctucanfd_base.c |  1 -
> >>   drivers/net/can/dev/skb.c                | 11 +++++++++++
> >>   include/uapi/linux/can.h                 |  4 ++--
> >>   net/can/af_can.c                         |  5 +++++
> >>   4 files changed, 18 insertions(+), 3 deletions(-)
> >
> > Would it be relevant to also set the flag when the skb is cloned?
> >
> > diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
> > index 182749e858b3..24de0bb7092e 100644
> > --- a/include/linux/can/skb.h
> > +++ b/include/linux/can/skb.h
> > @@ -85,6 +85,7 @@ static inline void can_skb_set_owner(struct sk_buff
> > *skb, struct sock *sk)
> >   static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
> >   {
> >          struct sk_buff *nskb;
> > +       struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
> >
> >          nskb = skb_clone(skb, GFP_ATOMIC);
> >          if (unlikely(!nskb)) {
> > @@ -92,6 +93,9 @@ static inline struct sk_buff
> > *can_create_echo_skb(struct sk_buff *skb)
> >                  return NULL;
> >          }
> >
> > +       if (can_is_canfd_skb(skb))
> > +               cfd->flags |= CANFD_FDF;
> > +
> >          can_skb_set_owner(nskb, skb->sk);
> >          consume_skb(skb);
> >          return nskb;
> >
>
> No, this should be obsolete.
>
> The current patch set should set this bit at all creation/malloc places
> of CAN FD skbs.
>
> >> diff --git a/drivers/net/can/ctucanfd/ctucanfd_base.c b/drivers/net/can/ctucanfd/ctucanfd_base.c
> >> index 3c18d028bd8c..c4026712ab7d 100644
> >> --- a/drivers/net/can/ctucanfd/ctucanfd_base.c
> >> +++ b/drivers/net/can/ctucanfd/ctucanfd_base.c
> >> @@ -655,11 +655,10 @@ static void ctucan_read_rx_frame(struct ctucan_priv *priv, struct canfd_frame *c
> >>                  cf->can_id = (idw & CAN_EFF_MASK) | CAN_EFF_FLAG;
> >>          else
> >>                  cf->can_id = (idw >> 18) & CAN_SFF_MASK;
> >>
> >>          /* BRS, ESI, RTR Flags */
> >> -       cf->flags = 0;
> >>          if (FIELD_GET(REG_FRAME_FORMAT_W_FDF, ffw)) {
> >>                  if (FIELD_GET(REG_FRAME_FORMAT_W_BRS, ffw))
> >>                          cf->flags |= CANFD_BRS;
> >>                  if (FIELD_GET(REG_FRAME_FORMAT_W_ESI_RSV, ffw))
> >>                          cf->flags |= CANFD_ESI;
> >> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> >> index b896e1ce3b47..adb413bdd734 100644
> >> --- a/drivers/net/can/dev/skb.c
> >> +++ b/drivers/net/can/dev/skb.c
> >> @@ -242,10 +242,13 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
> >>          can_skb_prv(skb)->ifindex = dev->ifindex;
> >>          can_skb_prv(skb)->skbcnt = 0;
> >>
> >>          *cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
> >>
> >> +       /* set CAN FD flag by default */
> >> +       (*cfd)->flags = CANFD_FDF;
> >> +
> >>          return skb;
> >>   }
> >>   EXPORT_SYMBOL_GPL(alloc_canfd_skb);
> >>
> >>   struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
> >> @@ -285,10 +288,18 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
> >>                          skb->pkt_type = PACKET_HOST;
> >>
> >>                  skb_reset_mac_header(skb);
> >>                  skb_reset_network_header(skb);
> >>                  skb_reset_transport_header(skb);
> >> +
> >> +               /* set CANFD_FDF flag for CAN FD frames */
> >> +               if (can_is_canfd_skb(skb)) {
> >> +                       struct canfd_frame *cfd;
> >> +
> >> +                       cfd = (struct canfd_frame *)skb->data;
> >> +                       cfd->flags |= CANFD_FDF;
> >> +               }
> >>          }
> >>
> >>          return true;
> >>   }
> >>
> >> diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
> >> index 90801ada2bbe..7b23eeeb3273 100644
> >> --- a/include/uapi/linux/can.h
> >> +++ b/include/uapi/linux/can.h
> >> @@ -139,12 +139,12 @@ struct can_frame {
> >>    * The struct can_frame and struct canfd_frame intentionally share the same
> >>    * layout to be able to write CAN frame content into a CAN FD frame structure.
> >>    * When this is done the former differentiation via CAN_MTU / CANFD_MTU gets
> >>    * lost. CANFD_FDF allows programmers to mark CAN FD frames in the case of
> >>    * using struct canfd_frame for mixed CAN / CAN FD content (dual use).
> >> - * N.B. the Kernel APIs do NOT provide mixed CAN / CAN FD content inside of
> >> - * struct canfd_frame therefore the CANFD_FDF flag is disregarded by Linux.
> >> + * Since the introduction of CAN XL the CANFD_FDF flag is set in all CAN FD
> >> + * frame structures provided by the CAN subsystem of the Linux kernel.
> >>    */
> >>   #define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
> >>   #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
> >>   #define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */
> >>
> >> diff --git a/net/can/af_can.c b/net/can/af_can.c
> >> index afa6c2151bc4..072a6a5c9dd1 100644
> >> --- a/net/can/af_can.c
> >> +++ b/net/can/af_can.c
> >> @@ -203,11 +203,16 @@ int can_send(struct sk_buff *skb, int loop)
> >>          int err = -EINVAL;
> >>
> >>          if (can_is_can_skb(skb)) {
> >>                  skb->protocol = htons(ETH_P_CAN);
> >>          } else if (can_is_canfd_skb(skb)) {
> >> +               struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
> >> +
> >>                  skb->protocol = htons(ETH_P_CANFD);
> >> +
> >> +               /* set CAN FD flag for CAN FD frames by default */
> >> +               cfd->flags |= CANFD_FDF;
> >>          } else {
> >>                  goto inval_skb;
> >>          }
> >>
> >>          /* Make sure the CAN frame can pass the selected CAN netdevice. */
> >
> > Once all the malloc and clone functions set the flag, is there still a
> > route that would reach the can_send() without setting the CANFD_FDF
> > flag? If the answer is supposedly no, maybe it is better to remove the
> > check (or maybe replace it with a debug message to identify missed use
> > cases).
>
> The flag IS set in all skb malloc places (and therefore does not need to
> be set in clone places (see my answer above).
>
> This specific check in can_send() especially covers content that came
> from userspace which is not setting this bit today.
>
> The same is done for userspace content provided by a PF_PACKET socket in
> can_skb_headroom_valid() above.

I see. So if I take the vcan driver as an example, can_send() would
set the flag and then, no need to set it again when cloning. Same goes
for the can_echo_skb. Thanks for the explanations.


Yours sincerely,
Vincent Mailhol



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux