From: Oliver Hartkopp <socketcan@hartkopp.net>
To: linux-can@vger.kernel.org
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Subject: [RFC PATCH v5 5/5] can: raw: add CAN XL support
Date: Tue, 19 Jul 2022 13:27:48 +0200 [thread overview]
Message-ID: <20220719112748.3281-6-socketcan@hartkopp.net> (raw)
In-Reply-To: <20220719112748.3281-1-socketcan@hartkopp.net>
Enable CAN_RAW sockets to read and write CAN XL frames analogue to the
CAN FD extension (new CAN_RAW_XL_FRAMES sockopt).
A CAN XL network interface is capable to handle Classical CAN, CAN FD and
CAN XL frames. When CAN_RAW_XL_FRAMES is enabled, the CAN_RAW socket checks
whether the addressed CAN network interface is capable to handle the
provided CAN frame.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
include/uapi/linux/can/raw.h | 1 +
net/can/raw.c | 89 ++++++++++++++++++++++++++++++------
2 files changed, 76 insertions(+), 14 deletions(-)
diff --git a/include/uapi/linux/can/raw.h b/include/uapi/linux/can/raw.h
index 3386aa81fdf2..ff12f525c37c 100644
--- a/include/uapi/linux/can/raw.h
+++ b/include/uapi/linux/can/raw.h
@@ -60,8 +60,9 @@ enum {
CAN_RAW_ERR_FILTER, /* set filter for error frames */
CAN_RAW_LOOPBACK, /* local loopback (default:on) */
CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */
+ CAN_RAW_XL_FRAMES, /* allow CAN XL frames (default:off) */
};
#endif /* !_UAPI_CAN_RAW_H */
diff --git a/net/can/raw.c b/net/can/raw.c
index d1bd9cc51ebe..0090fb785480 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -85,10 +85,11 @@ struct raw_sock {
int ifindex;
struct list_head notifier;
int loopback;
int recv_own_msgs;
int fd_frames;
+ int xl_frames;
int join_filters;
int count; /* number of active filters */
struct can_filter dfilter; /* default/single filter */
struct can_filter *filter; /* pointer to filter(s) */
can_err_mask_t err_mask;
@@ -127,12 +128,13 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
/* check the received tx sock reference */
if (!ro->recv_own_msgs && oskb->sk == sk)
return;
- /* do not pass non-CAN2.0 frames to a legacy socket */
- if (!ro->fd_frames && oskb->len != CAN_MTU)
+ /* make sure to not pass oversized frames to the socket */
+ if ((oskb->len > CAN_MTU && !ro->fd_frames && !ro->xl_frames) ||
+ (oskb->len == CANXL_MTU && !ro->xl_frames))
return;
/* eliminate multiple filter matches for the same skb */
if (this_cpu_ptr(ro->uniq)->skb == oskb &&
this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
@@ -344,10 +346,11 @@ static int raw_init(struct sock *sk)
/* set default loopback behaviour */
ro->loopback = 1;
ro->recv_own_msgs = 0;
ro->fd_frames = 0;
+ ro->xl_frames = 0;
ro->join_filters = 0;
/* alloc_percpu provides zero'ed memory */
ro->uniq = alloc_percpu(struct uniqframe);
if (unlikely(!ro->uniq))
@@ -667,10 +670,19 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
if (copy_from_sockptr(&ro->fd_frames, optval, optlen))
return -EFAULT;
break;
+ case CAN_RAW_XL_FRAMES:
+ if (optlen != sizeof(ro->xl_frames))
+ return -EINVAL;
+
+ if (copy_from_sockptr(&ro->xl_frames, optval, optlen))
+ return -EFAULT;
+
+ break;
+
case CAN_RAW_JOIN_FILTERS:
if (optlen != sizeof(ro->join_filters))
return -EINVAL;
if (copy_from_sockptr(&ro->join_filters, optval, optlen))
@@ -749,10 +761,16 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
if (len > sizeof(int))
len = sizeof(int);
val = &ro->fd_frames;
break;
+ case CAN_RAW_XL_FRAMES:
+ if (len > sizeof(int))
+ len = sizeof(int);
+ val = &ro->xl_frames;
+ break;
+
case CAN_RAW_JOIN_FILTERS:
if (len > sizeof(int))
len = sizeof(int);
val = &ro->join_filters;
break;
@@ -773,12 +791,17 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
struct sock *sk = sock->sk;
struct raw_sock *ro = raw_sk(sk);
struct sockcm_cookie sockc;
struct sk_buff *skb;
struct net_device *dev;
+ unsigned int skb_sz = size;
int ifindex;
- int err;
+ int err = -EINVAL;
+
+ /* valid CAN frame sizes */
+ if (size < CANXL_HDR_SZ + CANXL_MIN_DLEN || size > CANXL_MTU)
+ return -EINVAL;
if (msg->msg_name) {
DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name);
if (msg->msg_namelen < RAW_MIN_NAMELEN)
@@ -794,20 +817,15 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
dev = dev_get_by_index(sock_net(sk), ifindex);
if (!dev)
return -ENXIO;
- err = -EINVAL;
- if (ro->fd_frames && dev->mtu == CANFD_MTU) {
- if (unlikely(size != CANFD_MTU && size != CAN_MTU))
- goto put_dev;
- } else {
- if (unlikely(size != CAN_MTU))
- goto put_dev;
- }
+ /* alloc full CAN XL space */
+ if (ro->xl_frames && dev->mtu == CANXL_MTU)
+ skb_sz = CANXL_MTU;
- skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
+ skb = sock_alloc_send_skb(sk, skb_sz + sizeof(struct can_skb_priv),
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
goto put_dev;
can_skb_reserve(skb);
@@ -816,10 +834,43 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
err = memcpy_from_msg(skb_put(skb, size), msg, size);
if (err < 0)
goto free_skb;
+ err = -EINVAL;
+
+ if (ro->xl_frames && dev->mtu == CANXL_MTU) {
+ struct canxl_frame *cfx = (struct canxl_frame *)skb->data;
+
+ if (cfx->flags & CANXL_XLF) {
+ /* check for valid CAN XL frame */
+ if (cfx->len < CANXL_MIN_DLEN ||
+ cfx->len > CANXL_MAX_DLEN)
+ goto free_skb;
+
+ /* check truncated CAN XL frame structure */
+ if (size != cfx->len + CANXL_HDR_SZ)
+ goto free_skb;
+
+ /* push skb->len to CANXL_MTU */
+ if (size < CANXL_MTU)
+ skb_put_zero(skb, CANXL_MTU - size);
+ } else {
+ /* check for CAN FD and Classical CAN */
+ if (unlikely(size != CANFD_MTU && size != CAN_MTU))
+ goto free_skb;
+ }
+ } else if (ro->fd_frames && dev->mtu == CANFD_MTU) {
+ /* CAN FD and Classical CAN */
+ if (unlikely(size != CANFD_MTU && size != CAN_MTU))
+ goto free_skb;
+ } else {
+ /* Classical CAN */
+ if (unlikely(size != CAN_MTU))
+ goto free_skb;
+ }
+
sockcm_init(&sockc, sk);
if (msg->msg_controllen) {
err = sock_cmsg_send(sk, msg, &sockc);
if (unlikely(err))
goto free_skb;
@@ -850,25 +901,35 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
struct sock *sk = sock->sk;
+ struct raw_sock *ro = raw_sk(sk);
struct sk_buff *skb;
+ struct canxl_frame *cfx;
+ unsigned int rx_len;
int err = 0;
if (flags & MSG_ERRQUEUE)
return sock_recv_errqueue(sk, msg, size,
SOL_CAN_RAW, SCM_CAN_RAW_ERRQUEUE);
skb = skb_recv_datagram(sk, flags, &err);
if (!skb)
return err;
- if (size < skb->len)
+ rx_len = skb->len;
+ if (rx_len == CANXL_MTU) {
+ cfx = (struct canxl_frame *)skb->data;
+ if (cfx->len >= CANXL_MIN_DLEN && cfx->len < CANXL_MAX_DLEN)
+ rx_len = CANXL_HDR_SZ + cfx->len;
+ }
+
+ if (size < rx_len)
msg->msg_flags |= MSG_TRUNC;
else
- size = skb->len;
+ size = rx_len;
err = memcpy_to_msg(msg, skb->data, size);
if (err < 0) {
skb_free_datagram(sk, skb);
return err;
--
2.30.2
prev parent reply other threads:[~2022-07-19 11:28 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-19 11:27 [RFC PATCH v5 0/5] can: support CAN XL Oliver Hartkopp
2022-07-19 11:27 ` [RFC PATCH v5 1/5] can: canxl: introduce CAN XL data structure Oliver Hartkopp
2022-07-19 11:27 ` [RFC PATCH v5 2/5] can: canxl: introduce ETH_P_CANXL ethernet protocol handling Oliver Hartkopp
2022-07-19 11:27 ` [RFC PATCH v5 3/5] can: dev: add CAN XL support Oliver Hartkopp
2022-07-19 14:11 ` Vincent Mailhol
2022-07-19 14:38 ` Oliver Hartkopp
2022-07-19 15:16 ` Vincent Mailhol
2022-07-20 16:43 ` Oliver Hartkopp
2022-07-21 2:37 ` Vincent Mailhol
2022-07-21 3:13 ` Vincent Mailhol
2022-07-21 20:26 ` Oliver Hartkopp
2022-07-22 5:40 ` Vincent Mailhol
2022-07-21 7:36 ` Oliver Hartkopp
2022-07-21 7:53 ` Marc Kleine-Budde
2022-07-21 8:14 ` Vincent Mailhol
2022-07-21 19:09 ` Oliver Hartkopp
2022-07-22 3:20 ` Vincent Mailhol
2022-07-22 7:27 ` Marc Kleine-Budde
2022-07-22 8:33 ` Vincent Mailhol
2022-07-22 9:58 ` Marc Kleine-Budde
2022-07-22 10:54 ` Vincent Mailhol
2022-07-22 15:30 ` Oliver Hartkopp
2022-07-22 16:32 ` Vincent Mailhol
2022-07-22 18:52 ` Oliver Hartkopp
2022-07-23 2:39 ` Vincent Mailhol
2022-07-23 10:33 ` Oliver Hartkopp
2022-07-21 8:28 ` Vincent Mailhol
2022-07-19 11:27 ` [RFC PATCH v5 4/5] can: vcan: " Oliver Hartkopp
2022-07-19 11:27 ` Oliver Hartkopp [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220719112748.3281-6-socketcan@hartkopp.net \
--to=socketcan@hartkopp.net \
--cc=linux-can@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.