@@ -22,6 +22,17 @@ LOG_MODULE_REGISTER(net_sock_can, CONFIG_NET_SOCKETS_LOG_LEVEL);
2222
2323#include "sockets_internal.h"
2424
25+ #define MEM_ALLOC_TIMEOUT K_MSEC(50)
26+
27+ struct can_recv {
28+ struct net_if * iface ;
29+ struct net_context * ctx ;
30+ canid_t can_id ;
31+ canid_t can_mask ;
32+ };
33+
34+ static struct can_recv receivers [CONFIG_NET_SOCKETS_CAN_RECEIVERS ];
35+
2536extern const struct socket_op_vtable sock_fd_op_vtable ;
2637
2738static const struct socket_op_vtable can_sock_fd_op_vtable ;
@@ -77,32 +88,87 @@ static void zcan_received_cb(struct net_context *ctx, struct net_pkt *pkt,
7788 union net_proto_header * proto_hdr ,
7889 int status , void * user_data )
7990{
80- NET_DBG ("ctx %p pkt %p st %d ud %p" , ctx , pkt , status , user_data );
91+ /* The ctx parameter is not really relevant here. It refers to first
92+ * net_context that was used when registering CAN socket.
93+ * In practice there can be multiple sockets that are interested in
94+ * same CAN id packets. That is why we need to implement the dispatcher
95+ * which will give the packet to correct net_context(s).
96+ */
97+ struct net_pkt * clone = NULL ;
98+ int i ;
8199
82- /* if pkt is NULL, EOF */
83- if (!pkt ) {
84- struct net_pkt * last_pkt = k_fifo_peek_tail (& ctx -> recv_q );
100+ for (i = 0 ; i < ARRAY_SIZE (receivers ); i ++ ) {
101+ struct zcan_frame * zframe =
102+ (struct zcan_frame * )net_pkt_data (pkt );
103+ struct can_frame frame ;
104+
105+ if (receivers [i ].iface != net_pkt_iface (pkt )) {
106+ continue ;
107+ }
108+
109+ can_copy_zframe_to_frame (zframe , & frame );
85110
86- if (!last_pkt ) {
87- /* If there're no packets in the queue, recv() may
88- * be blocked waiting on it to become non-empty,
89- * so cancel that wait.
111+ if ((frame .can_id & receivers [i ].can_mask ) !=
112+ (receivers [i ].can_id & receivers [i ].can_mask )) {
113+ continue ;
114+ }
115+
116+ /* If there are multiple receivers configured, we use the
117+ * original net_pkt as a template, and just clone it to all
118+ * recipients. This is done like this so that we avoid the
119+ * original net_pkt being freed while we are cloning it.
120+ */
121+ if (pkt != NULL && ARRAY_SIZE (receivers ) > 1 ) {
122+ /* There are multiple receivers, we need to clone
123+ * the packet.
90124 */
91- sock_set_eof (ctx );
92- k_fifo_cancel_wait (& ctx -> recv_q );
93- NET_DBG ("Marked socket %p as peer-closed" , ctx );
125+ clone = net_pkt_clone (pkt , MEM_ALLOC_TIMEOUT );
126+ if (!clone ) {
127+ /* Sent the packet to at least one recipient
128+ * if there is no memory to clone the packet.
129+ */
130+ clone = pkt ;
131+ }
94132 } else {
95- net_pkt_set_eof (last_pkt , true);
96- NET_DBG ("Set EOF flag on pkt %p" , ctx );
133+ clone = pkt ;
97134 }
98135
99- return ;
100- }
136+ ctx = receivers [i ].ctx ;
137+
138+ NET_DBG ("[%d] ctx %p pkt %p st %d" , i , ctx , clone , status );
139+
140+ /* if pkt is NULL, EOF */
141+ if (!clone ) {
142+ struct net_pkt * last_pkt =
143+ k_fifo_peek_tail (& ctx -> recv_q );
144+
145+ if (!last_pkt ) {
146+ /* If there're no packets in the queue,
147+ * recv() may be blocked waiting on it to
148+ * become non-empty, so cancel that wait.
149+ */
150+ sock_set_eof (ctx );
151+ k_fifo_cancel_wait (& ctx -> recv_q );
152+
153+ NET_DBG ("Marked socket %p as peer-closed" , ctx );
154+ } else {
155+ net_pkt_set_eof (last_pkt , true);
156+
157+ NET_DBG ("Set EOF flag on pkt %p" , ctx );
158+ }
159+
160+ return ;
161+ } else {
162+ /* Normal packet */
163+ net_pkt_set_eof (clone , false);
101164
102- /* Normal packet */
103- net_pkt_set_eof (pkt , false);
165+ k_fifo_put (& ctx -> recv_q , clone );
166+ }
167+ }
104168
105- k_fifo_put (& ctx -> recv_q , pkt );
169+ if (clone && clone != pkt ) {
170+ net_pkt_unref (pkt );
171+ }
106172}
107173
108174static int zcan_bind_ctx (struct net_context * ctx , const struct sockaddr * addr ,
@@ -232,20 +298,18 @@ static ssize_t zcan_recvfrom_ctx(struct net_context *ctx, void *buf,
232298 }
233299
234300 if (net_pkt_read (pkt , (void * )& zframe , sizeof (zframe ))) {
301+ net_pkt_unref (pkt );
302+
235303 errno = EIO ;
236304 return -1 ;
237305 }
238306
239- if (!(flags & ZSOCK_MSG_PEEK )) {
240- net_pkt_unref (pkt );
241- } else {
242- net_pkt_cursor_init (pkt );
243- }
244-
245307 NET_ASSERT (recv_len == sizeof (struct can_frame ));
246308
247309 can_copy_zframe_to_frame (& zframe , (struct can_frame * )buf );
248310
311+ net_pkt_unref (pkt );
312+
249313 return recv_len ;
250314}
251315
@@ -361,52 +425,190 @@ static int can_sock_getsockopt_vmeth(void *obj, int level, int optname,
361425 return zcan_getsockopt_ctx (obj , level , optname , optval , optlen );
362426}
363427
428+ static int can_register_receiver (struct net_if * iface , struct net_context * ctx ,
429+ canid_t can_id , canid_t can_mask )
430+ {
431+ int i ;
432+
433+ NET_DBG ("Max %lu receivers" , ARRAY_SIZE (receivers ));
434+
435+ for (i = 0 ; i < ARRAY_SIZE (receivers ); i ++ ) {
436+ if (receivers [i ].ctx != NULL ) {
437+ continue ;
438+ }
439+
440+ receivers [i ].ctx = ctx ;
441+ receivers [i ].iface = iface ;
442+ receivers [i ].can_id = can_id ;
443+ receivers [i ].can_mask = can_mask ;
444+
445+ return i ;
446+ }
447+
448+ return - ENOENT ;
449+ }
450+
451+ static void can_unregister_receiver (struct net_if * iface ,
452+ struct net_context * ctx ,
453+ canid_t can_id , canid_t can_mask )
454+ {
455+ int i ;
456+
457+ for (i = 0 ; i < ARRAY_SIZE (receivers ); i ++ ) {
458+ if (receivers [i ].ctx == ctx &&
459+ receivers [i ].iface == iface &&
460+ receivers [i ].can_id == can_id &&
461+ receivers [i ].can_mask == can_mask ) {
462+ receivers [i ].ctx = NULL ;
463+ return ;
464+ }
465+ }
466+ }
467+
468+ static int can_register_filters (struct net_if * iface , struct net_context * ctx ,
469+ const struct can_filter * filters , int count )
470+ {
471+ int i , ret ;
472+
473+ NET_DBG ("Registering %d filters" , count );
474+
475+ for (i = 0 ; i < count ; i ++ ) {
476+ ret = can_register_receiver (iface , ctx , filters [i ].can_id ,
477+ filters [i ].can_mask );
478+ if (ret < 0 ) {
479+ goto revert ;
480+ }
481+ }
482+
483+ return 0 ;
484+
485+ revert :
486+ for (i = 0 ; i < count ; i ++ ) {
487+ can_unregister_receiver (iface , ctx , filters [i ].can_id ,
488+ filters [i ].can_mask );
489+ }
490+
491+ return ret ;
492+ }
493+
494+ static void can_unregister_filters (struct net_if * iface ,
495+ struct net_context * ctx ,
496+ const struct can_filter * filters ,
497+ int count )
498+ {
499+ int i ;
500+
501+ NET_DBG ("Unregistering %d filters" , count );
502+
503+ for (i = 0 ; i < count ; i ++ ) {
504+ can_unregister_receiver (iface , ctx , filters [i ].can_id ,
505+ filters [i ].can_mask );
506+ }
507+ }
508+
509+ static bool is_already_attached (struct can_filter * filter ,
510+ struct net_if * iface ,
511+ struct net_context * ctx )
512+ {
513+ int i ;
514+
515+ for (i = 0 ; i < ARRAY_SIZE (receivers ); i ++ ) {
516+ if (receivers [i ].ctx != ctx && receivers [i ].iface == iface &&
517+ ((receivers [i ].can_id & receivers [i ].can_mask ) ==
518+ (UNALIGNED_GET (& filter -> can_id ) &
519+ UNALIGNED_GET (& filter -> can_mask )))) {
520+ return true;
521+ }
522+ }
523+
524+ return false;
525+ }
526+
364527static int can_sock_setsockopt_vmeth (void * obj , int level , int optname ,
365528 const void * optval , socklen_t optlen )
366529{
367- if ( level == SOL_CAN_RAW ) {
368- const struct canbus_api * api ;
369- struct net_if * iface ;
370- struct device * dev ;
530+ const struct canbus_api * api ;
531+ struct net_if * iface ;
532+ struct device * dev ;
533+ int ret ;
371534
372- /* The application must use can_filter and then we convert
373- * it to zcan_filter as the CANBUS drivers expects that.
374- */
375- if (optname == CAN_RAW_FILTER &&
376- optlen != sizeof (struct can_filter )) {
377- errno = EINVAL ;
378- return -1 ;
379- }
535+ if (level != SOL_CAN_RAW ) {
536+ return zcan_setsockopt_ctx (obj , level , optname , optval , optlen );
537+ }
380538
381- if (optval == NULL ) {
539+ /* The application must use CAN_filter and then we convert
540+ * it to zcan_filter as the CANBUS drivers expects that.
541+ */
542+ if (optname == CAN_RAW_FILTER && optlen != sizeof (struct can_filter )) {
543+ errno = EINVAL ;
544+ return -1 ;
545+ }
546+
547+ if (optval == NULL ) {
548+ errno = EINVAL ;
549+ return -1 ;
550+ }
551+
552+ iface = net_context_get_iface (obj );
553+ dev = net_if_get_device (iface );
554+ api = dev -> driver_api ;
555+
556+ if (!api || !api -> setsockopt ) {
557+ errno = ENOTSUP ;
558+ return -1 ;
559+ }
560+
561+ if (optname == CAN_RAW_FILTER ) {
562+ int count , i ;
563+
564+ if (optlen % sizeof (struct can_filter ) != 0 ) {
382565 errno = EINVAL ;
383566 return -1 ;
384567 }
385568
386- iface = net_context_get_iface (obj );
387- dev = net_if_get_device (iface );
388- api = dev -> driver_api ;
569+ count = optlen / sizeof (struct can_filter );
389570
390- if (!api || !api -> setsockopt ) {
391- errno = ENOTSUP ;
571+ ret = can_register_filters (iface , obj , optval , count );
572+ if (ret < 0 ) {
573+ errno = - ret ;
392574 return -1 ;
393575 }
394576
395- if (optname == CAN_RAW_FILTER ) {
577+ for (i = 0 ; i < count ; i ++ ) {
578+ struct can_filter * filter ;
396579 struct zcan_filter zfilter ;
580+ bool duplicate ;
397581
398- can_copy_filter_to_zfilter ((struct can_filter * )optval ,
399- & zfilter );
582+ filter = & ((struct can_filter * )optval )[i ];
400583
401- return api -> setsockopt (dev , obj , level , optname ,
402- & zfilter , sizeof (zfilter ));
584+ /* If someone has already attached the same filter to
585+ * same interface, we do not need to do it here again.
586+ */
587+ duplicate = is_already_attached (filter , iface , obj );
588+ if (duplicate ) {
589+ continue ;
590+ }
591+
592+ can_copy_filter_to_zfilter (filter , & zfilter );
593+
594+ ret = api -> setsockopt (dev , obj , level , optname ,
595+ & zfilter , sizeof (zfilter ));
596+ if (ret < 0 ) {
597+ break ;
598+ }
599+ }
600+
601+ if (ret < 0 ) {
602+ can_unregister_filters (iface , obj , optval , count );
603+
604+ errno = - ret ;
605+ return -1 ;
403606 }
404607
405- return api -> setsockopt (dev , obj , level , optname ,
406- optval , optlen );
608+ return 0 ;
407609 }
408610
409- return zcan_setsockopt_ctx ( obj , level , optname , optval , optlen );
611+ return api -> setsockopt ( dev , obj , level , optname , optval , optlen );
410612}
411613
412614static const struct socket_op_vtable can_sock_fd_op_vtable = {
0 commit comments