All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Linux Netdev List <netdev@vger.kernel.org>,
	Linux CAN List <linux-can@vger.kernel.org>
Subject: Re: [RFC PATCH net-next] can-gw: add a variable limit for CAN frame routings
Date: Tue, 08 Jan 2013 09:40:52 +0100	[thread overview]
Message-ID: <50EBDB94.3000705@pengutronix.de> (raw)
In-Reply-To: <50EB4377.6030306@hartkopp.net>

[-- Attachment #1: Type: text/plain, Size: 6405 bytes --]

On 01/07/2013 10:51 PM, Oliver Hartkopp wrote:
> To prevent a possible misconfiguration (e.g. circular CAN frame routings)
> limit the number of routings of a single CAN frame to a small variable value.
> 
> The limit can be specified by the module parameter 'max_hops' (1..6).
> The default value is 1 (one hop), according to the original can-gw behaviour.
> 
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> 
> ---
> 
> Having the possibility of only a single CAN frame routing (one hop) hinders
> use-cases for some complex application setups. To enable more than one CAN
> frame routing process with a single CAN frame (skb) a counter needed to be
> implemented to prevent an endless frame processing (e.g. due to some kind of
> misconfiguration).
> 
> As the skb control buffer (cb) potentially gets modified by net/sched in the
> tx path the csum element for IP checksums is re-used for the counter, as CAN
> frame skbs (ARPHRD_CAN) never contain any kind of checksums (see src comment).
> 
> @Marc: I wanted to sent this patch on netdev ML to see if there are any
> objections of using skb->csum in the way i proposed here. When the patch is
> fine please take it via can-next for this net-next cycle then. Tnx.

Fine with me. I'll take the patch as usual, once it's ready. See a
nitpick inline.

> diff --git a/include/uapi/linux/can/gw.h b/include/uapi/linux/can/gw.h
> index 8e1db18..ba87697 100644
> --- a/include/uapi/linux/can/gw.h
> +++ b/include/uapi/linux/can/gw.h
> @@ -44,6 +44,7 @@ enum {
>  	CGW_SRC_IF,	/* ifindex of source network interface */
>  	CGW_DST_IF,	/* ifindex of destination network interface */
>  	CGW_FILTER,	/* specify struct can_filter on source CAN device */
> +	CGW_DELETED,	/* number of deleted CAN frames (see max_hops param) */
>  	__CGW_MAX
>  };
>  
> diff --git a/net/can/gw.c b/net/can/gw.c
> index 574dda78e..20d5a7d 100644
> --- a/net/can/gw.c
> +++ b/net/can/gw.c
> @@ -57,15 +57,23 @@
>  #include <net/net_namespace.h>
>  #include <net/sock.h>
>  
> -#define CAN_GW_VERSION "20101209"
> +#define CAN_GW_VERSION "20130107"
>  static __initconst const char banner[] =
> -	KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
> +	KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")";
>  
>  MODULE_DESCRIPTION("PF_CAN netlink gateway");
>  MODULE_LICENSE("Dual BSD/GPL");
>  MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
>  MODULE_ALIAS("can-gw");
>  
> +#define CAN_GW_MAX_HOPS 6
> +
> +static unsigned int max_hops __read_mostly = 1;
> +module_param(max_hops, uint, S_IRUGO);
> +MODULE_PARM_DESC(max_hops,
> +		 "maximum can-gw routing hops for CAN frames "
> +		 "(valid values: 1-6 hops, default: 1)");
> +
>  static HLIST_HEAD(cgw_list);
>  static struct notifier_block notifier;
>  
> @@ -118,6 +126,7 @@ struct cgw_job {
>  	struct rcu_head rcu;
>  	u32 handled_frames;
>  	u32 dropped_frames;
> +	u32 deleted_frames;
>  	struct cf_mod mod;
>  	union {
>  		/* CAN frame data source */
> @@ -338,9 +347,27 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
>  	struct sk_buff *nskb;
>  	int modidx = 0;
>  
> -	/* do not handle already routed frames - see comment below */
> -	if (skb_mac_header_was_set(skb))
> +	/*
> +	 * Do not handle CAN frames routed more than 'max_hops' times.
> +	 * In general we should never catch this delimiter which is intended
> +	 * to cover a misconfiguration protection (e.g. circular CAN routes).
> +	 *
> +	 * The Controller Area Network controllers only accept CAN frames with
> +	 * correct CRCs - which are not visible in the controller registers.
> +	 * According to skbuff.h documentation the csum element for IP checksums
> +	 * is undefined/unsued when ip_summed == CHECKSUM_UNNECESSARY. Only
> +	 * CAN skbs can be processed here which already have this property.
> +	 */
> +
> +#define cgw_hops(skb) ((skb)->csum)
> +
> +	BUG_ON(skb->ip_summed != CHECKSUM_UNNECESSARY);
> +
> +	if (cgw_hops(skb) >= max_hops) {
> +		/* indicate deleted frames due to misconfiguration */
> +		gwj->deleted_frames++;
>  		return;
> +	}
>  
>  	if (!(gwj->dst.dev->flags & IFF_UP)) {
>  		gwj->dropped_frames++;
> @@ -363,15 +390,8 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
>  		return;
>  	}
>  
> -	/*
> -	 * Mark routed frames by setting some mac header length which is
> -	 * not relevant for the CAN frames located in the skb->data section.
> -	 *
> -	 * As dev->header_ops is not set in CAN netdevices no one is ever
> -	 * accessing the various header offsets in the CAN skbuffs anyway.
> -	 * E.g. using the packet socket to read CAN frames is still working.
> -	 */
> -	skb_set_mac_header(nskb, 8);
> +	/* put the incremented hop counter in the cloned skb */
> +	cgw_hops(nskb) = cgw_hops(skb) + 1;
>  	nskb->dev = gwj->dst.dev;
>  
>  	/* pointer to modifiable CAN frame */
> @@ -472,6 +492,11 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
>  			goto cancel;
>  	}
>  
> +	if (gwj->deleted_frames) {
> +		if (nla_put_u32(skb, CGW_DELETED, gwj->deleted_frames) < 0)
> +			goto cancel;
> +	}
> +
>  	/* check non default settings of attributes */
>  
>  	if (gwj->mod.modtype.and) {
> @@ -771,6 +796,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
>  
>  	gwj->handled_frames = 0;
>  	gwj->dropped_frames = 0;
> +	gwj->deleted_frames = 0;
>  	gwj->flags = r->flags;
>  	gwj->gwtype = r->gwtype;
>  
> @@ -895,7 +921,14 @@ static int cgw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
>  
>  static __init int cgw_module_init(void)
>  {
> -	printk(banner);
> +	/* sanitize given module parameter */
> +	if (max_hops < 1)
> +		max_hops = 1;
> +
> +	if (max_hops > CAN_GW_MAX_HOPS)
> +		max_hops = CAN_GW_MAX_HOPS;

You can make use of clamp(val, min, max) here.

> +
> +	printk("%s max_hops=%d\n", banner, max_hops);
>  
>  	cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
>  				      0, 0, NULL);

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 261 bytes --]

  reply	other threads:[~2013-01-08  8:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-07 21:51 [RFC PATCH net-next] can-gw: add a variable limit for CAN frame routings Oliver Hartkopp
2013-01-08  8:40 ` Marc Kleine-Budde [this message]
2013-01-08 10:26   ` Oliver Hartkopp
2013-01-08 11:56     ` Marc Kleine-Budde

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=50EBDB94.3000705@pengutronix.de \
    --to=mkl@pengutronix.de \
    --cc=linux-can@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=socketcan@hartkopp.net \
    /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.