lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 13 Aug 2013 11:08:41 +0200
From:	Benedikt Spranger <b.spranger@...utronix.de>
To:	netdev@...r.kernel.org
Cc:	Alexander Frank <Alexander.Frank@...rspaecher.com>,
	Sebastian Andrzej Siewior <bigeasy@...utronix.de>,
	Benedikt Spranger <b.spranger@...utronix.de>
Subject: [PATCH 6/7] net: add the AF_FLEXRAY protocol

FlexRay is a networking technology used in automotive fields as
successor of the Controller Area Network (CAN). It provides the
core functionality and a RAW protocol driver.

Signed-off-by: Benedikt Spranger <b.spranger@...utronix.de>
---
 Documentation/networking/00-INDEX             |   2 +
 Documentation/networking/flexray.txt          |  24 ++
 include/linux/flexray.h                       | 168 ++++++++
 include/linux/flexray/core.h                  |  45 +++
 include/linux/flexray/dev.h                   |  64 +++
 include/linux/socket.h                        |   4 +-
 include/uapi/linux/flexray/Kbuild             |   4 +
 include/uapi/linux/flexray/flexcard_netlink.h |  53 +++
 include/uapi/linux/flexray/netlink.h          | 203 ++++++++++
 include/uapi/linux/flexray/raw.h              |  16 +
 include/uapi/linux/if_arp.h                   |   1 +
 include/uapi/linux/if_ether.h                 |   1 +
 net/Kconfig                                   |   1 +
 net/Makefile                                  |   1 +
 net/core/sock.c                               |   9 +-
 net/flexray/Kconfig                           |  28 ++
 net/flexray/Makefile                          |   9 +
 net/flexray/af_flexray.c                      | 548 ++++++++++++++++++++++++++
 net/flexray/af_flexray.h                      |  59 +++
 net/flexray/proc.c                            | 196 +++++++++
 net/flexray/raw.c                             | 446 +++++++++++++++++++++
 21 files changed, 1878 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/networking/flexray.txt
 create mode 100644 include/linux/flexray.h
 create mode 100644 include/linux/flexray/core.h
 create mode 100644 include/linux/flexray/dev.h
 create mode 100644 include/uapi/linux/flexray/Kbuild
 create mode 100644 include/uapi/linux/flexray/flexcard_netlink.h
 create mode 100644 include/uapi/linux/flexray/netlink.h
 create mode 100644 include/uapi/linux/flexray/raw.h
 create mode 100644 net/flexray/Kconfig
 create mode 100644 net/flexray/Makefile
 create mode 100644 net/flexray/af_flexray.c
 create mode 100644 net/flexray/af_flexray.h
 create mode 100644 net/flexray/proc.c
 create mode 100644 net/flexray/raw.c

diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 18b64b2..1cb180e 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -74,6 +74,8 @@ fib_trie.txt
 	- Level Compressed Trie (LC-trie) notes: a structure for routing.
 filter.txt
 	- Linux Socket Filtering
+flexray.txt
+	- FlexRay Protocol Family
 fore200e.txt
 	- FORE Systems PCA-200E/SBA-200E ATM NIC driver info.
 framerelay.txt
diff --git a/Documentation/networking/flexray.txt b/Documentation/networking/flexray.txt
new file mode 100644
index 0000000..9c0b844
--- /dev/null
+++ b/Documentation/networking/flexray.txt
@@ -0,0 +1,24 @@
+============================================================================
+
+flexray.txt
+
+Readme file for the FlexRay Protocol Family (aka Socket FlexRay)
+
+This file contains
+
+  1 Overview / What is Socket FlexRay
+
+============================================================================
+
+1 Overview / What is Socket FlexRay
+-----------------------------------
+
+The socket FlexRay package is an implementation of FlexRay protocols
+for Linux. FlexRay is a networking technology used in automotive fields as
+successor of the Controller Area Network (CAN). It is designed to be faster
+and more reliable than CAN.
+The Socket FlexRay implementation uses the Berkeley socket API, the Linux
+network stack and implements the FlexRay device drivers as network interfaces.
+The FlexRay socket API has been designed as similar as possible to the TCP/IP
+protocols to allow programmers, familiar with network programming, to easily
+learn how to use FlexRay sockets.
diff --git a/include/linux/flexray.h b/include/linux/flexray.h
new file mode 100644
index 0000000..75e07e8
--- /dev/null
+++ b/include/linux/flexray.h
@@ -0,0 +1,168 @@
+/*
+ * linux/flexray.h
+ *
+ * Definitions for FlexRay network layer (socket addr / FlexRay frame)
+ *
+ */
+
+#ifndef FLEXRAY_H
+#define FLEXRAY_H
+
+#include <linux/types.h>
+#include <linux/socket.h>
+
+/* FlexRay kernel definitions */
+
+/* special address description flags for the FLEXRAY_ID */
+#define FLEXRAY_PPI_FLAG	0x40 /* Payload preamble indicator */
+#define FLEXRAY_NFI_FLAG	0x20 /* Null frame indikator */
+#define FLEXRAY_SYN_FLAG	0x10 /* Sync frame indikator */
+#define FLEXRAY_SFI_FLAG	0x08 /* Startup frame indikator */
+
+/*
+ * FlexRay Frame structure
+ *
+ * Bit 0     reserved
+ * Bit 1     Payload preamble indicator
+ * Bit 2     Null frame indikator
+ * Bit 3     Sync frame indikator
+ * Bit 4     Startup frame indikator
+ * Bit 5-15  Frame ID
+ * Bit 16-22 Payload length
+ * Bit 23-33 Header CRC
+ * Bit 34-39 Cycle count
+ * PAYLOAD [0-254 Bytes]
+ * 24 Bit CRC
+ */
+
+/* define Flexray Header Type for Filters */
+typedef __u64 flexray_header_t;
+
+/**
+ * struct flexray_frame - basic FlexRay frame structure
+ * @head:	Header
+ * @data:       the FlexRay frame payload.
+ * @crc:	the FlexRay frame CRC
+ */
+
+struct flexray_frame {
+	__u8		head[5];
+	__u8		data[254] __aligned(8);
+	__u8		crc[3];
+};
+
+static inline int flexray_get_ppi(__u8 *head)
+{
+	return !!(head[0] & FLEXRAY_PPI_FLAG);
+}
+
+static inline void flexray_set_ppi(int ppi, __u8 *head)
+{
+	if (ppi)
+		head[0] |= FLEXRAY_PPI_FLAG;
+	else
+		head[0] &= ~FLEXRAY_PPI_FLAG;
+}
+
+static inline int flexray_get_nfi(__u8 *head)
+{
+	return !!(head[0] & FLEXRAY_NFI_FLAG);
+}
+
+static inline void flexray_set_nfi(int nfi, __u8 *head)
+{
+	if (nfi)
+		head[0] |= FLEXRAY_NFI_FLAG;
+	else
+		head[0] &= ~FLEXRAY_NFI_FLAG;
+}
+
+static inline int flexray_get_syn(__u8 *head)
+{
+	return !!(head[0] & FLEXRAY_SYN_FLAG);
+}
+
+static inline void flexray_set_syn(int syn, __u8 *head)
+{
+	if (syn)
+		head[0] |= FLEXRAY_SYN_FLAG;
+	else
+		head[0] &= ~FLEXRAY_SYN_FLAG;
+}
+
+static inline int flexray_get_sfi(__u8 *head)
+{
+	return !!(head[0] & FLEXRAY_SFI_FLAG);
+}
+
+static inline void flexray_set_sfi(int sfi, __u8 *head)
+{
+	if (sfi)
+		head[0] |= FLEXRAY_SFI_FLAG;
+	else
+		head[0] &= ~FLEXRAY_SFI_FLAG;
+}
+
+static inline __u16 flexray_get_id(__u8 *head)
+{
+	return ((head[0] & 0x3) << 8) | head[1];
+}
+
+static inline void flexray_set_id(__u16 id, __u8 *head)
+{
+	head[0] &= ~0x3;
+	head[0] |= (id >> 8) & 0x3;
+	head[1] = id & 0xff;
+}
+
+static inline __u8 flexray_get_pl(__u8 *head)
+{
+	return head[2] >> 1;
+}
+
+static inline void flexray_set_pl(__u8 pl, __u8 *head)
+{
+	head[2] &= 0x1;
+	head[2] |= pl << 1;
+}
+
+static inline __u16 flexray_get_hcrc(__u8 *head)
+{
+	return ((head[2] & 0x1) << 10) | (head[3] << 2) | (head[4] >> 6);
+}
+
+static inline void flexray_set_hcrc(__u16 hcrc, __u8 *head)
+{
+	head[2] &= 0xfe;
+	head[4] &= 0x3f;
+	head[2] |= (hcrc >> 10) & 0x1;
+	head[3] = (hcrc >> 2) & 0xff;
+	head[4] |= (hcrc & 0x3) << 6;
+}
+
+static inline __u8 flexray_get_cc(__u8 *head)
+{
+	return head[4] & 0x3f;
+}
+
+static inline void flexray_set_cc(__u8 cc, __u8 *head)
+{
+	head[4] &= ~0x3f;
+	head[4] |= cc & 0x3f;
+}
+
+/* particular protocols of the protocol family PF_FLEXRAY */
+#define FLEXRAY_RAW	1 /* RAW sockets */
+#define FLEXRAY_NPROTO	2
+
+struct sockaddr_flexray {
+	sa_family_t	flexray_family;
+	int		flexray_ifindex;
+};
+
+struct flexray_filter {
+	flexray_header_t flexray_id;
+	flexray_header_t flexray_mask;
+};
+
+#endif /* FLEXRAY_H */
diff --git a/include/linux/flexray/core.h b/include/linux/flexray/core.h
new file mode 100644
index 0000000..90a0f06
--- /dev/null
+++ b/include/linux/flexray/core.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved.
+ */
+
+#ifndef FLEXRAY_CORE_H
+#define FLEXRAY_CORE_H
+
+#include <linux/flexray.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#define DNAME(dev) ((dev) ? (dev)->name : "any")
+
+/**
+ * struct flexray_proto - FlexRay protocol structure
+ * @type:       type argument in socket() syscall, e.g. SOCK_DGRAM.
+ * @protocol:   protocol number in socket() syscall.
+ * @ops:        pointer to struct proto_ops for sock->ops.
+ * @prot:       pointer to struct proto structure.
+ */
+struct flexray_proto {
+	int type;
+	int protocol;
+	const struct proto_ops *ops;
+	struct proto *prot;
+};
+
+/* function prototypes for the FlexRay networklayer core (af_flexray.c) */
+
+extern int  flexray_proto_register(const struct flexray_proto *frp);
+extern void flexray_proto_unregister(const struct flexray_proto *frp);
+
+extern int  flexray_rx_register(struct net_device *dev,
+				void (*func)(struct sk_buff *, void *),
+				void *data, char *ident);
+
+extern void flexray_rx_unregister(struct net_device *dev,
+				  void (*func)(struct sk_buff *, void *),
+				  void *data);
+
+extern int flexray_send(struct sk_buff *skb);
+extern int flexray_ioctl(struct socket *sock, unsigned int cmd,
+			 unsigned long arg);
+
+#endif /* FLEXRAY_CORE_H */
diff --git a/include/linux/flexray/dev.h b/include/linux/flexray/dev.h
new file mode 100644
index 0000000..999ebab
--- /dev/null
+++ b/include/linux/flexray/dev.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved.
+ */
+
+#ifndef FLEXRAY_DEV_H
+#define FLEXRAY_DEV_H
+
+#include <linux/flexray.h>
+#include <linux/flexray/netlink.h>
+
+/* FlexRay common private data */
+
+struct flexray_priv {
+	struct flexray_device_stats flexray_stats;
+
+	enum flexray_state state;
+
+	int (*do_get_state)(const struct net_device *dev,
+			    enum flexray_state *state);
+	int (*do_set_state)(struct net_device *dev,
+			    enum flexray_state state);
+	int (*do_validate)(struct sk_buff *skb);
+
+	struct flexray_cluster_param cluster;
+	struct flexray_node_param node;
+	struct flexray_symbol_param symbol;
+	__u32 sw_filter[FLEXRAY_MAX_SW_FILTER];
+	u8 version;
+};
+
+/* Drop a given socketbuffer if it does not contain a valid FlexRay frame. */
+static inline int flexray_dropped_invalid_skb(struct net_device *dev,
+					      struct sk_buff *skb)
+{
+	const struct flexray_frame *frf = (struct flexray_frame *)skb->data;
+
+	if (unlikely(skb->len != sizeof(*frf))) {
+		kfree_skb(skb);
+		dev->stats.tx_dropped++;
+		return 1;
+	}
+
+	return 0;
+}
+
+struct net_device *alloc_flexraydev(int sizeof_priv, u8 version);
+void free_flexraydev(struct net_device *dev);
+
+int open_flexraydev(struct net_device *dev);
+void close_flexraydev(struct net_device *dev);
+
+int register_flexraydev(struct net_device *dev);
+void unregister_flexraydev(struct net_device *dev);
+
+int flexray_restart_now(struct net_device *dev);
+
+struct sk_buff *alloc_flexray_skb(struct net_device *dev,
+				  struct flexray_frame **cf);
+
+void print_cluster_config(struct flexray_cluster_param *cp, int is_v3);
+void print_node_config(struct flexray_node_param *np, int is_v3);
+void print_symbol_config(struct flexray_symbol_param *sp);
+
+#endif /* FLEXRAY_DEV_H */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 230c04b..a7c316b 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -180,7 +180,8 @@ struct ucred {
 #define AF_ALG		38	/* Algorithm sockets		*/
 #define AF_NFC		39	/* NFC sockets			*/
 #define AF_VSOCK	40	/* vSockets			*/
-#define AF_MAX		41	/* For now.. */
+#define AF_FLEXRAY	41	/* Flexray			*/
+#define AF_MAX		42	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
@@ -225,6 +226,7 @@ struct ucred {
 #define PF_ALG		AF_ALG
 #define PF_NFC		AF_NFC
 #define PF_VSOCK	AF_VSOCK
+#define PF_FLEXRAY	AF_FLEXRAY
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/include/uapi/linux/flexray/Kbuild b/include/uapi/linux/flexray/Kbuild
new file mode 100644
index 0000000..8c45658
--- /dev/null
+++ b/include/uapi/linux/flexray/Kbuild
@@ -0,0 +1,4 @@
+header-y += error.h
+header-y += netlink.h
+header-y += raw.h
+header-y += flexcard_netlink.h
diff --git a/include/uapi/linux/flexray/flexcard_netlink.h b/include/uapi/linux/flexray/flexcard_netlink.h
new file mode 100644
index 0000000..d04e2dd
--- /dev/null
+++ b/include/uapi/linux/flexray/flexcard_netlink.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved.
+ */
+
+#ifndef _FLEXCARD_NETLINK_H
+#define _FLEXCARD_NETLINK_H
+
+#include <linux/types.h>
+
+#define FC_MSGBUF_VERSION	1
+
+/* Start Flexcard flags beyond ERAY flags */
+#define FC_MSGBUF_ACK		0x00010000
+#define FC_MSGBUF_ACK_NULL	0x00020000
+#define FC_MSGBUF_ACK_PAYLOAD	0x00040000
+#define FC_MSGBUF_SELFSYNC	0x00080000
+
+struct fc_msgbuf_cfg {
+	__u32 flags;
+	__u8 buf_id;
+	__u8 cyc;
+	__u16 len;
+	__u16 max;
+	__u16 start;
+	__u32 frame_id;
+	__u32 reject_mask;
+	enum eray_msgbuf_type type;
+	enum eray_msgbuf_channel channel;
+} __packed;
+
+/* commands */
+enum fc_msgbuf_cmd {
+	FC_MSGBUF_CMD_UNSPEC,
+	FC_MSGBUF_CMD_GET_CFG,
+	FC_MSGBUF_CMD_SET_CFG,
+	FC_MSGBUF_CMD_RESET_CFG,
+	FC_MSGBUF_CMD_READ_CFG,
+	__FC_MSGBUF_CMD_MAX,
+};
+#define FC_MSGBUF_CMD_MAX (__FC_MSGBUF_CMD_MAX - 1)
+
+/* attributes */
+enum fc_msgbuf_attr {
+	FC_MSGBUF_ATTR_UNSPEC,
+	FC_MSGBUF_ATTR_BUF_ID,
+	FC_MSGBUF_ATTR_DEV_ID,
+	FC_MSGBUF_ATTR_DEV_NAME,
+	FC_MSGBUF_ATTR_CFG,
+	__FC_MSGBUF_ATTR_MAX,
+};
+#define FC_MSGBUF_ATTR_MAX (__FC_MSGBUF_ATTR_MAX - 1)
+
+#endif /* _FLEXCARD_NETLINK_H */
diff --git a/include/uapi/linux/flexray/netlink.h b/include/uapi/linux/flexray/netlink.h
new file mode 100644
index 0000000..3d1dbaf
--- /dev/null
+++ b/include/uapi/linux/flexray/netlink.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved.
+ */
+
+#ifndef FLEXRAY_NETLINK_H
+#define FLEXRAY_NETLINK_H
+
+#include <linux/types.h>
+
+#define FLEXRAY_MAX_SW_FILTER	2048
+
+/*
+ * FlexRay operational and error states
+ */
+enum flexray_state {
+	FLEXRAY_STATE_UNSPEC,
+	FLEXRAY_STATE_DEFAULT_CONFIG,
+	FLEXRAY_STATE_CONFIG,
+	FLEXRAY_STATE_READY,
+	FLEXRAY_STATE_WAKEUP,
+	FLEXRAY_STATE_STARTUP,
+	FLEXRAY_STATE_NORMAL_ACTIVE,
+	FLEXRAY_STATE_NORMAL_PASSIVE,
+	FLEXRAY_STATE_HALT,
+	FLEXRAY_STATE_MONITOR_MODE,
+	FLEXRAY_STATE_COLDSTART,
+	FLEXRAY_STATE_MAX
+};
+
+/*
+ * FlexRay device statistics
+ */
+struct flexray_device_stats {
+	__u32 txack;
+	__u32 manage;
+	__u32 info;
+	__u32 status;
+	__u32 notify;
+};
+
+/*
+ * FlexRay netlink interface
+ */
+enum {
+	IFLA_FLEXRAY_UNSPEC,
+	IFLA_FLEXRAY_STATE,
+	IFLA_FLEXRAY_VERSION,
+	IFLA_FLEXRAY_CLUSTER,
+	IFLA_FLEXRAY_NODE,
+	IFLA_FLEXRAY_SYMBOL,
+	IFLA_FLEXRAY_SW_FILTER,
+	__IFLA_FLEXRAY_MAX
+};
+
+#define IFLA_FLEXRAY_MAX    (__IFLA_FLEXRAY_MAX - 1)
+
+/*
+ * FlexRay filter netlink interface
+ */
+enum {
+	IFLA_FLEXRAY_FILTER_UNSPEC,
+	IFLA_FLEXRAY_FILTER_ENTRY,
+	__IFLA_FLEXRAY_FILTER_MAX
+};
+
+#define IFLA_FLEXRAY_FILTER_MAX    (__IFLA_FLEXRAY_FILTER_MAX - 1)
+
+struct cluster_v2 {
+	__u16 gAssumedPrecision;
+	__u8 gdMaxInitializationError;
+	__u8 gdMaxMicrotick;
+	__u8 gdMaxPropagationDelay;
+	__u8 gdMinPropagationDelay;
+	__u8 gdWakeupSymbolRxIdle;
+	__u8 gdWakeupSymbolRxLow;
+	__u16 gdWakeupSymbolRxWindow;
+	__u8 gdWakeupSymbolTxIdle;
+	__u8 gdWakeupSymbolTxLow;
+	__u32 gOffsetCorrectionMax;
+	__u16 gOffsetCorrectionStart;
+	__u8 gSyncNodeMax;
+};
+
+struct cluster_v3 {
+	__u16 gClockDeviationMax;
+	__u8 gCycleCountMax;
+	__u8 gdIgnoreAfterTx;
+	__u8 gdSymbolWindowActionPointOffset;
+	__u8 gdWakeupRxIdle;
+	__u8 gdWakeupRxLow;
+	__u16 gdWakeupRxWindow;
+	__u8 gdWakeupTxActive;
+	__u8 gdWakeupTxIdle;
+	__u8 gExternOffsetCorrection;
+	__u8 gExternRateCorrection;
+	__u8 gSyncFrameIDCountMax;
+};
+
+struct flexray_cluster_param {
+	/* Protocol relevant */
+	__u8 gColdstartAttempts;
+	__u8 gdActionPointOffset;
+	__u8 gdCASRxLowMax;
+	__u8 gdDynamicSlotIdlePhase;
+	__u8 gdMinislot;
+	__u8 gdMinislotActionPointOffset;
+	__u16 gdStaticSlot;
+	__u8 gdSymbolWindow;
+	__u8 gdTSSTransmitter;
+	__u8 gListenNoise;
+	__u16 gMacroPerCycle;
+	__u8 gMaxWithoutClockCorrectionFatal;
+	__u8 gMaxWithoutClockCorrectionPassive;
+	__u16 gNumberOfMinislots;
+	__u16 gNumberOfStaticSlots;
+	__u8 gPayloadLengthStatic;
+
+	/* Protocol related */
+	__u8 gChannels;
+	__u8 gClusterDriftDamping;
+	__u8 gdBit;
+	__u16 gdCycle;
+	__u8 gdMacrotick;
+	__u16 gdNIT;
+	__u8 gdSampleClockPeriod;
+	__u8 gNetworkManagementVectorLength;
+	union {
+		struct cluster_v2 v2;
+		struct cluster_v3 v3;
+	};
+};
+
+struct node_v2 {
+	__u16 pdMaxDrift;
+	__u8 pMicroPerMacroNom;
+	__u8 pSingleSlotEnabled;
+};
+
+struct node_v3 {
+	__u8 pExternalSync;
+	__u8 pFallBackInternal;
+	__u8 pKeySlotOnlyEnabled;
+	__u8 pNMVectorEarlyUpdate;
+	__u8 pOffsetCorrectionStart;
+	__u8 pSecondKeySlotID;
+	__u8 pTwoKeySlotMode;
+};
+
+struct flexray_node_param {
+	/* Protocol relevant */
+	__u8 pAllowHaltDueToClock;
+	__u8 pAllowPassiveToActive;
+	__u8 pChannels;
+	__u8 pClusterDriftDamping;
+	__u16 pdAcceptedStartupRange;
+	__u8 pDecodingCorrection;
+	__u8 pDelayCompensationA;
+	__u8 pDelayCompensationB;
+	__u32 pdListenTimeout;
+	__s8 vExternOffsetControl;
+	__s8 vExternRateControl;
+	__u8 pExternOffsetCorrection;
+	__u8 pExternRateCorrection;
+	__u16 pKeySlotID;
+	__u8 pKeySlotUsedForStartup;
+	__u8 pKeySlotUsedForSync;
+	__u16 pLatestTx;
+	__u8 pMacroInitialOffsetA;
+	__u8 pMacroInitialOffsetB;
+	__u16 pMicroInitialOffsetA;
+	__u16 pMicroInitialOffsetB;
+	__u32 pMicroPerCycle;
+	__u16 pOffsetCorrectionOut;
+	__u16 pRateCorrectionOut;
+	__u8 pWakeupChannel;
+	__u8 pWakeupPattern;
+
+	/* Protocol related */
+	__u8 pdMicrotick;
+	__u8 pPayloadLengthDynMax;
+	__u8 pSamplesPerMicrotick;
+
+	union {
+		struct node_v2 v2;
+		struct node_v3 v3;
+	};
+};
+
+struct flexray_symbol_param {
+	/* Protocol related */
+	__u8 pChannelsMTS;
+};
+
+/*
+ * FlexRay software ID filter
+ */
+
+struct flexray_sw_filter {
+	__u32 pos;
+	__u32 id;
+};
+
+#endif /* FLEXRAY_NETLINK_H */
diff --git a/include/uapi/linux/flexray/raw.h b/include/uapi/linux/flexray/raw.h
new file mode 100644
index 0000000..0b12068
--- /dev/null
+++ b/include/uapi/linux/flexray/raw.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved.
+ */
+
+#ifndef FLEXRAY_RAW_H
+#define FLEXRAY_RAW_H
+
+#include <linux/flexray.h>
+
+/* for socket options affecting the socket (not the global system) */
+
+enum {
+	FLEXRAY_RAW_FILTER = 1,     /* set 0 .. n can_filter(s) */
+};
+
+#endif
diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h
index d7fea34..d64971f 100644
--- a/include/uapi/linux/if_arp.h
+++ b/include/uapi/linux/if_arp.h
@@ -53,6 +53,7 @@
 #define ARPHRD_X25	271		/* CCITT X.25			*/
 #define ARPHRD_HWX25	272		/* Boards with X.25 in firmware	*/
 #define ARPHRD_CAN	280		/* Controller Area Network      */
+#define ARPHRD_FLEXRAY	290		/* FlexRay			*/
 #define ARPHRD_PPP	512
 #define ARPHRD_CISCO	513		/* Cisco HDLC	 		*/
 #define ARPHRD_HDLC	ARPHRD_CISCO
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index ade07f1..05e886e 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -112,6 +112,7 @@
 #define ETH_P_LOCALTALK 0x0009		/* Localtalk pseudo type 	*/
 #define ETH_P_CAN	0x000C		/* CAN: Controller Area Network */
 #define ETH_P_CANFD	0x000D		/* CANFD: CAN flexible data rate*/
+#define ETH_P_FLEXRAY	0x000F		/* Flexray			*/
 #define ETH_P_PPPTALK	0x0010		/* Dummy type for Atalk over PPP*/
 #define ETH_P_TR_802_2	0x0011		/* 802.2 frames 		*/
 #define ETH_P_MOBITEX	0x0015		/* Mobitex (kaz@...e.net)	*/
diff --git a/net/Kconfig b/net/Kconfig
index ee02136..8b7e604 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -328,6 +328,7 @@ endmenu
 
 source "net/ax25/Kconfig"
 source "net/can/Kconfig"
+source "net/flexray/Kconfig"
 source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
 source "net/rxrpc/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index 9492e8c..8d03e63 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_NETROM)		+= netrom/
 obj-$(CONFIG_ROSE)		+= rose/
 obj-$(CONFIG_AX25)		+= ax25/
 obj-$(CONFIG_CAN)		+= can/
+obj-$(CONFIG_FLEXRAY)		+= flexray/
 obj-$(CONFIG_IRDA)		+= irda/
 obj-$(CONFIG_BT)		+= bluetooth/
 obj-$(CONFIG_SUNRPC)		+= sunrpc/
diff --git a/net/core/sock.c b/net/core/sock.c
index 83667de..820e44e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -213,7 +213,8 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
   "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
   "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
   "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
-  "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_MAX"
+  "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_FLEXRAY"  ,
+  "sk_lock-AF_MAX"
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
@@ -229,7 +230,8 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
   "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
   "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
-  "slock-AF_NFC"   , "slock-AF_VSOCK"    ,"slock-AF_MAX"
+  "slock-AF_NFC"   , "slock-AF_VSOCK"    , "slock-AF_FLEXRAY"  ,
+  "slock-AF_MAX"
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
@@ -245,7 +247,8 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
   "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
   "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
-  "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_MAX"
+  "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_FLEXRAY"  ,
+  "clock-AF_MAX"
 };
 
 /*
diff --git a/net/flexray/Kconfig b/net/flexray/Kconfig
new file mode 100644
index 0000000..18d9d69
--- /dev/null
+++ b/net/flexray/Kconfig
@@ -0,0 +1,28 @@
+#
+# FlexRay network layer core configuration
+#
+
+menuconfig FLEXRAY
+	depends on NET
+	tristate "FlexRay bus subsystem support"
+	---help---
+	  FlexRay is a slow (up to 10Mbit/s) serial communications
+	  protocol which was developed by the FlexRay Consortium, a
+	  cooperation of leading companies in the automotive industry, from
+	  2000 till 2010, which result in ISO 10681.
+	  More information on the FlexRay network protocol family PF_FLEXRAY
+	  is contained in <Documentation/networking/flexray.txt>.
+
+	  If you want FLEXRAY support you should say Y here and also to the
+	  specific driver for your controller(s) below.
+
+config FLEXRAY_RAW
+	tristate "Raw FlexRay Protocol"
+	depends on FLEXRAY
+	default N
+	---help---
+	  The raw FlexRay protocol option offers access to the FlexRay bus
+	  via the BSD socket API. You probably want to use the raw socket in
+	  most cases where no higher level protocol is being used.
+	  To receive/send raw FLEXRAY messages, use AF_FLEXRAY with protocol
+	  FLEXRAY_RAW.
diff --git a/net/flexray/Makefile b/net/flexray/Makefile
new file mode 100644
index 0000000..f5e05b6c
--- /dev/null
+++ b/net/flexray/Makefile
@@ -0,0 +1,9 @@
+#
+#  Makefile for the Linux FlexRay core.
+#
+
+obj-$(CONFIG_FLEXRAY)		+= flexray.o
+flexray-y			:= af_flexray.o proc.o
+
+obj-$(CONFIG_FLEXRAY_RAW)	+= flexray-raw.o
+flexray-raw-y			:= raw.o
diff --git a/net/flexray/af_flexray.c b/net/flexray/af_flexray.c
new file mode 100644
index 0000000..e5fd1c4
--- /dev/null
+++ b/net/flexray/af_flexray.c
@@ -0,0 +1,548 @@
+/* Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/uaccess.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/socket.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/skbuff.h>
+#include <linux/flexray.h>
+#include <linux/flexray/core.h>
+#include <linux/flexray/dev.h>
+#include <linux/ratelimit.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
+
+#include "af_flexray.h"
+
+/* receive filters subscribed for 'all' FlexRay devices */
+struct dev_rcv_lists flexray_rx_alldev_list;
+static DEFINE_SPINLOCK(flexray_rcvlists_lock);
+
+static struct kmem_cache *rcv_cache __read_mostly;
+
+/* table of registered FlexRay protocols */
+static const struct flexray_proto *proto_tab[FLEXRAY_NPROTO] __read_mostly;
+static DEFINE_MUTEX(proto_tab_lock);
+
+struct s_stats	flexray_stats;	/* packet statistics */
+struct s_pstats	flexray_pstats;	/* receive list statistics */
+
+/* af_flexray socket functions */
+
+int flexray_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+
+	switch (cmd) {
+
+	case SIOCGSTAMP:
+		return sock_get_timestamp(sk, (struct timeval __user *)arg);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+EXPORT_SYMBOL(flexray_ioctl);
+
+static void flexray_sock_destruct(struct sock *sk)
+{
+	skb_queue_purge(&sk->sk_receive_queue);
+}
+
+static const struct flexray_proto *flexray_get_proto(int protocol)
+{
+	const struct flexray_proto *frp;
+
+	rcu_read_lock();
+	frp = rcu_dereference(proto_tab[protocol]);
+	if (frp && !try_module_get(frp->prot->owner))
+		frp = NULL;
+	rcu_read_unlock();
+
+	return frp;
+}
+
+static inline void flexray_put_proto(const struct flexray_proto *frp)
+{
+	module_put(frp->prot->owner);
+}
+
+static int flexray_create(struct net *net, struct socket *sock, int protocol,
+			  int kern)
+{
+	struct sock *sk;
+	const struct flexray_proto *frp;
+	int err = 0;
+
+	sock->state = SS_UNCONNECTED;
+
+	if (protocol < 0 || protocol >= FLEXRAY_NPROTO)
+		return -EINVAL;
+
+	if (!net_eq(net, &init_net))
+		return -EAFNOSUPPORT;
+
+	frp = flexray_get_proto(protocol);
+
+#ifdef CONFIG_MODULES
+	if (!frp) {
+		request_module("flexray-proto-%d", protocol);
+		frp = flexray_get_proto(protocol);
+	}
+#endif
+	/* check for available protocol and correct usage */
+	if (!frp)
+		return -EPROTONOSUPPORT;
+
+	if (frp->type != sock->type) {
+		err = -EPROTOTYPE;
+		goto errout;
+	}
+
+	sock->ops = frp->ops;
+
+	sk = sk_alloc(net, PF_FLEXRAY, GFP_KERNEL, frp->prot);
+	if (!sk) {
+		err = -ENOMEM;
+		goto errout;
+	}
+
+	sock_init_data(sock, sk);
+	sk->sk_destruct = flexray_sock_destruct;
+
+	if (sk->sk_prot->init)
+		err = sk->sk_prot->init(sk);
+
+	if (err) {
+		/* release sk on errors */
+		sock_orphan(sk);
+		sock_put(sk);
+	}
+
+errout:
+	flexray_put_proto(frp);
+	return err;
+}
+
+/**
+ * flexray_send - transmit a FlexRay frame
+ * @skb: pointer to socket buffer with FlexRay frame in data section
+ *
+ * Return:
+ *  0 on success
+ *  -ENETDOWN when the selected interface is down
+ *  -ENOBUFS on full driver queue (see net_xmit_errno())
+ *  -EPERM when trying to send on a non-FlexRay interface
+ *  -EINVAL when the skb->data does not contain a valid FlexRay frame
+ *  The skb is always consumed.
+ */
+int flexray_send(struct sk_buff *skb)
+{
+	struct flexray_priv *priv;
+	int err;
+
+	priv = netdev_priv(skb->dev);
+
+	if (skb->dev->type != ARPHRD_FLEXRAY) {
+		err = -EPERM;
+		goto err_skb;
+	}
+
+	if (!(skb->dev->flags & IFF_UP)) {
+		err = -ENETDOWN;
+		goto err_skb;
+	}
+
+	if (!priv->do_validate) {
+		err = -EINVAL;
+		goto err_skb;
+	}
+
+	err = priv->do_validate(skb);
+	if (err)
+		goto err_skb;
+
+	skb->protocol = htons(ETH_P_FLEXRAY);
+	skb_reset_network_header(skb);
+	skb_reset_transport_header(skb);
+
+	skb->pkt_type = PACKET_HOST;
+
+	/* send to netdevice */
+	err = dev_queue_xmit(skb);
+	if (err > 0) {
+		err = net_xmit_errno(err);
+		return err;
+	}
+
+	/* update statistics */
+	flexray_stats.tx_frames++;
+
+	return 0;
+err_skb:
+	kfree_skb(skb);
+	return err;
+}
+EXPORT_SYMBOL(flexray_send);
+
+/* af_flexray rx path */
+
+static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
+{
+	if (!dev)
+		return &flexray_rx_alldev_list;
+	else
+		return (struct dev_rcv_lists *)dev->ml_priv;
+}
+
+int flexray_rx_register(struct net_device *dev,
+			void (*func)(struct sk_buff *, void *),
+			void *data, char *ident)
+{
+	struct receiver *r;
+	struct dev_rcv_lists *d;
+	int err = 0;
+
+	if (dev && dev->type != ARPHRD_FLEXRAY)
+		return -ENODEV;
+
+	r = kmem_cache_alloc(rcv_cache, GFP_KERNEL);
+	if (!r)
+		return -ENOMEM;
+
+	spin_lock(&flexray_rcvlists_lock);
+
+	d = find_dev_rcv_lists(dev);
+	if (d) {
+		r->func		= func;
+		r->data		= data;
+		r->ident	= ident;
+
+		hlist_add_head_rcu(&r->list, &d->rx[RX_ALL]);
+		d->entries++;
+
+		flexray_pstats.rcv_entries++;
+		if (flexray_pstats.rcv_entries_max < flexray_pstats.rcv_entries)
+			flexray_pstats.rcv_entries_max =
+				flexray_pstats.rcv_entries;
+	} else {
+		kmem_cache_free(rcv_cache, r);
+		err = -ENODEV;
+	}
+
+	spin_unlock(&flexray_rcvlists_lock);
+
+	return err;
+}
+EXPORT_SYMBOL(flexray_rx_register);
+
+static void flexray_rx_delete_receiver(struct rcu_head *rp)
+{
+	struct receiver *r = container_of(rp, struct receiver, rcu);
+
+	kmem_cache_free(rcv_cache, r);
+}
+
+void flexray_rx_unregister(struct net_device *dev,
+			   void (*func)(struct sk_buff *, void *), void *data)
+{
+	struct receiver *r = NULL;
+	struct hlist_head *rl;
+	struct dev_rcv_lists *d;
+	bool found = false;
+
+	if (dev && dev->type != ARPHRD_FLEXRAY)
+		return;
+
+	spin_lock(&flexray_rcvlists_lock);
+
+	d = find_dev_rcv_lists(dev);
+	if (!d) {
+		netdev_err(dev, "BUG: receive list not found\n");
+		goto out;
+	}
+
+	rl = &d->rx[RX_ALL];
+
+	/* Search the receiver list for the item to delete. This should
+	 * exist, since no receiver may be unregistered that hasn't
+	 * been registered before.
+	 */
+
+	hlist_for_each_entry_rcu(r, rl, list) {
+		if (r->func == func && r->data == data) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		netdev_err(dev, "BUG: receive list entry not found\n");
+		r = NULL;
+		goto out;
+	}
+
+	hlist_del_rcu(&r->list);
+	d->entries--;
+
+	if (flexray_pstats.rcv_entries > 0)
+		flexray_pstats.rcv_entries--;
+
+	/* remove device structure requested by NETDEV_UNREGISTER */
+	if (d->remove_on_zero_entries && !d->entries) {
+		kfree(d);
+		dev->ml_priv = NULL;
+	}
+
+out:
+	spin_unlock(&flexray_rcvlists_lock);
+
+	/* schedule the receiver item for deletion */
+	if (r)
+		call_rcu(&r->rcu, flexray_rx_delete_receiver);
+}
+EXPORT_SYMBOL(flexray_rx_unregister);
+
+static inline void deliver(struct sk_buff *skb, struct receiver *r)
+{
+	r->func(skb, r->data);
+}
+
+static int flexray_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
+{
+	struct receiver *r;
+	int matches = 0;
+
+	if (d->entries == 0)
+		return 0;
+
+	/* check for unfiltered entries */
+	hlist_for_each_entry_rcu(r, &d->rx[RX_ALL], list) {
+		deliver(skb, r);
+		matches++;
+	}
+
+	return matches;
+}
+
+static int flexray_rcv(struct sk_buff *skb, struct net_device *dev,
+		       struct packet_type *pt, struct net_device *orig_dev)
+{
+	struct dev_rcv_lists *d;
+	struct flexray_frame *frf = (struct flexray_frame *)skb->data;
+	int matches;
+
+	if (!net_eq(dev_net(dev), &init_net))
+		goto drop;
+
+	if (WARN_ONCE(dev->type != ARPHRD_FLEXRAY,
+		      "PF_FLEXRAY: dropped non conform skbuf: "
+		      "dev type %d, len %d, payload %d\n",
+		      dev->type, skb->len, flexray_get_pl(frf->head)))
+		goto drop;
+
+	/* update statistics */
+	flexray_stats.rx_frames++;
+
+	rcu_read_lock();
+
+	/* deliver the packet to sockets listening on all devices */
+	matches = flexray_rcv_filter(&flexray_rx_alldev_list, skb);
+
+	/* find receive list for this device */
+	d = find_dev_rcv_lists(dev);
+	if (d)
+		matches += flexray_rcv_filter(d, skb);
+
+	rcu_read_unlock();
+
+	/* consume the skbuff allocated by the netdevice driver */
+	consume_skb(skb);
+
+	if (matches > 0)
+		flexray_stats.matches++;
+
+	return NET_RX_SUCCESS;
+
+drop:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+
+/* af_flexray protocol functions */
+int flexray_proto_register(const struct flexray_proto *frp)
+{
+	int proto = frp->protocol;
+	int err = 0;
+
+	if (proto < 0 || proto >= FLEXRAY_NPROTO) {
+		pr_err("flexray: protocol number %d out of range\n", proto);
+		return -EINVAL;
+	}
+
+	err = proto_register(frp->prot, 0);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&proto_tab_lock);
+
+	if (proto_tab[proto]) {
+		pr_err("flexray: protocol %d already registered\n",
+		       proto);
+		err = -EBUSY;
+	} else
+		rcu_assign_pointer(proto_tab[proto], frp);
+
+	mutex_unlock(&proto_tab_lock);
+
+	if (err < 0)
+		proto_unregister(frp->prot);
+
+	return err;
+}
+EXPORT_SYMBOL(flexray_proto_register);
+
+void flexray_proto_unregister(const struct flexray_proto *frp)
+{
+	int proto = frp->protocol;
+
+	mutex_lock(&proto_tab_lock);
+	BUG_ON(proto_tab[proto] != frp);
+	rcu_assign_pointer(proto_tab[proto], NULL);
+	mutex_unlock(&proto_tab_lock);
+
+	synchronize_rcu();
+
+	proto_unregister(frp->prot);
+}
+EXPORT_SYMBOL(flexray_proto_unregister);
+
+/* af_flexray notifier to create/remove FlexRay netdevice specific structs */
+static int flexray_notifier(struct notifier_block *nb, unsigned long msg,
+			    void *data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct dev_rcv_lists *d;
+
+	if (!net_eq(dev_net(dev), &init_net))
+		return NOTIFY_DONE;
+
+	if (dev->type != ARPHRD_FLEXRAY)
+		return NOTIFY_DONE;
+
+	switch (msg) {
+
+	case NETDEV_REGISTER:
+		/* create new dev_rcv_lists for this device */
+		d = kzalloc(sizeof(*d), GFP_KERNEL);
+		if (!d) {
+			netdev_err(dev, "allocation of receive list failed\n");
+			return NOTIFY_DONE;
+		}
+		BUG_ON(dev->ml_priv);
+		dev->ml_priv = d;
+
+		break;
+
+	case NETDEV_UNREGISTER:
+		spin_lock(&flexray_rcvlists_lock);
+
+		d = dev->ml_priv;
+		if (d) {
+			if (d->entries)
+				d->remove_on_zero_entries = 1;
+			else {
+				kfree(d);
+				dev->ml_priv = NULL;
+			}
+		} else
+			netdev_err(dev, "notifier: receive list not found\n");
+
+		spin_unlock(&flexray_rcvlists_lock);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+/* af_flexray module init/exit functions */
+
+static struct packet_type flexray_packet __read_mostly = {
+	.type = cpu_to_be16(ETH_P_FLEXRAY),
+	.func = flexray_rcv,
+};
+
+static const struct net_proto_family flexray_family_ops = {
+	.family = PF_FLEXRAY,
+	.create = flexray_create,
+	.owner  = THIS_MODULE,
+};
+
+/* notifier block for netdevice event */
+static struct notifier_block flexray_netdev_notifier __read_mostly = {
+	.notifier_call = flexray_notifier,
+};
+
+static __init int flexray_init(void)
+{
+	memset(&flexray_rx_alldev_list, 0, sizeof(flexray_rx_alldev_list));
+
+	rcv_cache = kmem_cache_create("flexray_receiver",
+				      sizeof(struct receiver), 0, 0, NULL);
+	if (!rcv_cache)
+		return -ENOMEM;
+
+	flexray_init_proc();
+
+	/* protocol register */
+	sock_register(&flexray_family_ops);
+	register_netdevice_notifier(&flexray_netdev_notifier);
+	dev_add_pack(&flexray_packet);
+	return 0;
+}
+module_init(flexray_init);
+
+static __exit void flexray_exit(void)
+{
+	struct net_device *dev;
+
+	flexray_remove_proc();
+
+	/* protocol unregister */
+	dev_remove_pack(&flexray_packet);
+	unregister_netdevice_notifier(&flexray_netdev_notifier);
+	sock_unregister(PF_FLEXRAY);
+
+	/* remove created dev_rcv_lists from still registered FlexRay devices */
+	rcu_read_lock();
+	for_each_netdev_rcu(&init_net, dev) {
+		if (dev->type == ARPHRD_FLEXRAY && dev->ml_priv) {
+			struct dev_rcv_lists *d = dev->ml_priv;
+
+			BUG_ON(d->entries);
+			kfree(d);
+			dev->ml_priv = NULL;
+		}
+	}
+	rcu_read_unlock();
+
+	rcu_barrier(); /* Wait for completion of call_rcu()'s */
+
+	kmem_cache_destroy(rcv_cache);
+}
+module_exit(flexray_exit);
+
+MODULE_DESCRIPTION("FlexRay PF_FLEXRAY core");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Benedikt Spranger <b.spranger@...utronix.de>");
+
+MODULE_ALIAS_NETPROTO(PF_FLEXRAY);
diff --git a/net/flexray/af_flexray.h b/net/flexray/af_flexray.h
new file mode 100644
index 0000000..5aec894
--- /dev/null
+++ b/net/flexray/af_flexray.h
@@ -0,0 +1,59 @@
+/* Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved */
+
+#ifndef AF_FLEXRAY_H
+#define AF_FLEXRAY_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+#include <linux/flexray.h>
+
+/* af_flexray rx dispatcher structures */
+
+struct receiver {
+	struct hlist_node list;
+	struct rcu_head rcu;
+	void (*func)(struct sk_buff *, void *);
+	void *data;
+	char *ident;
+};
+
+enum {RX_ALL, RX_MAX};
+
+/* per device receive filters linked at dev->ml_priv */
+struct dev_rcv_lists {
+	struct hlist_head rx[RX_MAX];
+	struct hlist_head rx_sff[0x800];
+	int remove_on_zero_entries;
+	int entries;
+};
+
+/* can be reset e.g. by flexray_init_stats() */
+struct s_stats {
+	unsigned long rx_frames;
+	unsigned long tx_frames;
+	unsigned long matches;
+};
+
+/* persistent statistics */
+struct s_pstats {
+	unsigned long stats_reset;
+	unsigned long user_reset;
+	unsigned long rcv_entries;
+	unsigned long rcv_entries_max;
+};
+
+/* function prototypes for the FlexRay networklayer procfs (proc.c) */
+extern void flexray_init_proc(void);
+extern void flexray_remove_proc(void);
+extern void flexray_stat_update(unsigned long data);
+
+/* structures and variables from af_flexray.c needed in proc.c for reading */
+extern struct s_stats	flexray_stats;		/* packet statistics */
+extern struct s_pstats	flexray_pstats;		/* receive list statistics */
+extern struct hlist_head flexray_rx_dev_list;	/* rx dispatcher structures */
+/* receive filters subscribed for 'all' FlexRay devices */
+extern struct dev_rcv_lists flexray_rx_alldev_list;
+
+#endif /* AF_FLEXRAY_H */
diff --git a/net/flexray/proc.c b/net/flexray/proc.c
new file mode 100644
index 0000000..e82f844
--- /dev/null
+++ b/net/flexray/proc.c
@@ -0,0 +1,196 @@
+/* Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved */
+
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+#include <linux/if_arp.h>
+#include <linux/flexray/core.h>
+
+#include "af_flexray.h"
+
+/* proc filenames for the PF_FLEXRAY core */
+
+#define FLEXRAY_PROC_STATS       "stats"
+#define FLEXRAY_PROC_RESET_STATS "reset_stats"
+#define FLEXRAY_PROC_RCVLIST_ALL "rcvlist_all"
+#define FLEXRAY_PROC_RCVLIST_FIL "rcvlist_fil"
+
+static struct proc_dir_entry *flexray_dir;
+static struct proc_dir_entry *pde_stats;
+static struct proc_dir_entry *pde_reset_stats;
+static struct proc_dir_entry *pde_rcvlist_all;
+
+static const char rx_list_name[][8] = {
+	[RX_ALL] = "rx_all",
+};
+
+static void flexray_print_rcvlist(struct seq_file *m,
+				  struct hlist_head *rx_list,
+				  struct net_device *dev)
+{
+	struct receiver *r;
+
+	hlist_for_each_entry_rcu(r, rx_list, list)
+		seq_printf(m, "   %-5s     %pK  %pK  %s\n",
+				DNAME(dev), r->func, r->data, r->ident);
+}
+
+static void flexray_print_recv_banner(struct seq_file *m)
+{
+	seq_puts(m, "  device   flexray_id   flexray_mask  function"
+		 "  userdata   matches  ident\n");
+}
+
+static int flexray_stats_proc_show(struct seq_file *m, void *v)
+{
+	seq_putc(m, '\n');
+	seq_printf(m, " %8ld transmitted frames (TXF)\n",
+		   flexray_stats.tx_frames);
+	seq_printf(m, " %8ld received frames (RXF)\n",
+		   flexray_stats.rx_frames);
+	seq_printf(m, " %8ld matched frames (RXMF)\n",
+		   flexray_stats.matches);
+
+	seq_putc(m, '\n');
+
+	seq_printf(m, " %8ld current receive list entries (CRCV)\n",
+		   flexray_pstats.rcv_entries);
+	seq_printf(m, " %8ld maximum receive list entries (MRCV)\n",
+		   flexray_pstats.rcv_entries_max);
+
+	if (flexray_pstats.stats_reset)
+		seq_printf(m, "\n %8ld statistic resets (STR)\n",
+			   flexray_pstats.stats_reset);
+
+	if (flexray_pstats.user_reset)
+		seq_printf(m, " %8ld user statistic resets (USTR)\n",
+			   flexray_pstats.user_reset);
+
+	seq_putc(m, '\n');
+	return 0;
+}
+
+static int flexray_stats_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, flexray_stats_proc_show, NULL);
+}
+
+static const struct file_operations flexray_stats_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= flexray_stats_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int flexray_reset_stats_proc_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "Performed statistic reset #%ld.\n",
+		   flexray_pstats.stats_reset);
+
+	return 0;
+}
+
+static int flexray_reset_stats_proc_open(struct inode *inode,
+					 struct file *file)
+{
+	return single_open(file, flexray_reset_stats_proc_show, NULL);
+}
+
+static const struct file_operations flexray_reset_stats_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= flexray_reset_stats_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void flexray_rcvlist_proc_show_one(struct seq_file *m, int idx,
+						 struct net_device *dev,
+						 struct dev_rcv_lists *d)
+{
+	if (!hlist_empty(&d->rx[idx])) {
+		flexray_print_recv_banner(m);
+		flexray_print_rcvlist(m, &d->rx[idx], dev);
+	} else
+		seq_printf(m, "  (%s: no entry)\n", DNAME(dev));
+}
+
+static int flexray_rcvlist_proc_show(struct seq_file *m, void *v)
+{
+	int idx = (int)(long)m->private;
+	struct net_device *dev;
+	struct dev_rcv_lists *d;
+
+	seq_printf(m, "\nreceive list '%s':\n", rx_list_name[idx]);
+
+	rcu_read_lock();
+
+	/* receive list for 'all' FlexRay devices (dev == NULL) */
+	d = &flexray_rx_alldev_list;
+	flexray_rcvlist_proc_show_one(m, idx, NULL, d);
+
+	/* receive list for registered FlexRay devices */
+	for_each_netdev_rcu(&init_net, dev) {
+		if (dev->type == ARPHRD_FLEXRAY && dev->ml_priv)
+			flexray_rcvlist_proc_show_one(m, idx, dev,
+						      dev->ml_priv);
+	}
+
+	rcu_read_unlock();
+
+	seq_putc(m, '\n');
+	return 0;
+}
+
+static int flexray_rcvlist_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, flexray_rcvlist_proc_show, PDE_DATA(inode));
+}
+
+static const struct file_operations flexray_rcvlist_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= flexray_rcvlist_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void flexray_remove_proc_readentry(const char *name)
+{
+	remove_proc_entry(name, flexray_dir);
+}
+
+void flexray_init_proc(void)
+{
+	int perm = S_IRUGO | S_IWUSR;
+
+	flexray_dir = proc_mkdir("flexray", init_net.proc_net);
+	if (!flexray_dir)
+		return;
+
+	pde_stats = proc_create(FLEXRAY_PROC_STATS, perm, flexray_dir,
+			&flexray_stats_proc_fops);
+	pde_reset_stats = proc_create(FLEXRAY_PROC_RESET_STATS, perm,
+			flexray_dir, &flexray_reset_stats_proc_fops);
+	pde_rcvlist_all = proc_create_data(FLEXRAY_PROC_RCVLIST_ALL, perm,
+			flexray_dir, &flexray_rcvlist_proc_fops,
+			(void *)RX_ALL);
+}
+
+void flexray_remove_proc(void)
+{
+	if (!flexray_dir)
+		return;
+	if (pde_stats)
+		flexray_remove_proc_readentry(FLEXRAY_PROC_STATS);
+
+	if (pde_reset_stats)
+		flexray_remove_proc_readentry(FLEXRAY_PROC_RESET_STATS);
+
+	if (pde_rcvlist_all)
+		flexray_remove_proc_readentry(FLEXRAY_PROC_RCVLIST_ALL);
+
+	remove_proc_entry("flexray", init_net.proc_net);
+}
diff --git a/net/flexray/raw.c b/net/flexray/raw.c
new file mode 100644
index 0000000..78fd0de
--- /dev/null
+++ b/net/flexray/raw.c
@@ -0,0 +1,446 @@
+/* Copyright 2012 Eberspächer Electronics GmbH & Co. KG. All Rights Reserved */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/uio.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/socket.h>
+#include <linux/if_arp.h>
+#include <linux/skbuff.h>
+#include <linux/flexray.h>
+#include <linux/flexray/core.h>
+#include <linux/flexray/raw.h>
+#include <net/sock.h>
+#include <net/net_namespace.h>
+
+#define MASK_ALL 0
+
+struct flexray_raw_sock {
+	struct sock sk;
+	int bound;
+	int ifindex;
+	struct notifier_block notifier;
+	struct flexray_filter dfilter;	/* default/single filter */
+};
+
+static inline unsigned int *raw_flags(struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(skb->cb) <= (sizeof(struct sockaddr_flexray) +
+					 sizeof(unsigned int)));
+
+	/* return pointer after struct sockaddr_flexray */
+	return (unsigned int *)(&((struct sockaddr_flexray *)skb->cb)[1]);
+}
+
+static inline struct flexray_raw_sock *raw_sk(const struct sock *sk)
+{
+	return (struct flexray_raw_sock *)sk;
+}
+
+static void raw_rcv(struct sk_buff *oskb, void *data)
+{
+	struct sock *sk = (struct sock *)data;
+	struct sockaddr_flexray *addr;
+	struct sk_buff *skb;
+	unsigned int *pflags;
+
+	/* check the received tx sock reference */
+	if (oskb->sk == sk)
+		return;
+
+	/* clone the given skb to be able to enqueue it into the rcv queue */
+	skb = skb_clone(oskb, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	/*  Put the datagram to the queue so that raw_recvmsg() can
+	 *  get it from there.  We need to pass the interface index to
+	 *  raw_recvmsg().  We pass a whole struct sockaddr_flexray in skb->cb
+	 *  containing the interface index.
+	 */
+
+	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct sockaddr_flexray));
+	addr = (struct sockaddr_flexray *)skb->cb;
+	memset(addr, 0, sizeof(*addr));
+	addr->flexray_family  = AF_FLEXRAY;
+	addr->flexray_ifindex = skb->dev->ifindex;
+
+	/* add FlexRay specific message flags for raw_recvmsg() */
+	pflags = raw_flags(skb);
+	*pflags = 0;
+	if (oskb->sk)
+		*pflags |= MSG_DONTROUTE;
+	if (oskb->sk == sk)
+		*pflags |= MSG_CONFIRM;
+
+	if (sock_queue_rcv_skb(sk, skb) < 0)
+		kfree_skb(skb);
+}
+
+static int raw_enable_allfilters(struct net_device *dev, struct sock *sk)
+{
+	return flexray_rx_register(dev, raw_rcv, sk, "raw");
+}
+
+static inline void raw_disable_allfilters(struct net_device *dev,
+					  struct sock *sk)
+{
+	flexray_rx_unregister(dev, raw_rcv, sk);
+}
+
+static struct flexray_raw_sock *nb_to_raw_sock(struct notifier_block *nb)
+{
+	return container_of(nb, struct flexray_raw_sock, notifier);
+}
+
+static int raw_notifier(struct notifier_block *nb,
+			unsigned long msg, void *data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct flexray_raw_sock *ro = nb_to_raw_sock(nb);
+	struct sock *sk = &ro->sk;
+
+	if (!net_eq(dev_net(dev), &init_net))
+		return NOTIFY_DONE;
+
+	if (dev->type != ARPHRD_FLEXRAY)
+		return NOTIFY_DONE;
+
+	if (ro->ifindex != dev->ifindex)
+		return NOTIFY_DONE;
+
+	switch (msg) {
+
+	case NETDEV_UNREGISTER:
+		lock_sock(sk);
+		/* remove current filters & unregister */
+		if (ro->bound)
+			raw_disable_allfilters(dev, sk);
+
+		ro->ifindex = 0;
+		ro->bound   = 0;
+		release_sock(sk);
+
+		sk->sk_err = ENODEV;
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_error_report(sk);
+		break;
+
+	case NETDEV_DOWN:
+		sk->sk_err = ENETDOWN;
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_error_report(sk);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int raw_init(struct sock *sk)
+{
+	struct flexray_raw_sock *ro = raw_sk(sk);
+
+	ro->bound			= 0;
+	ro->ifindex			= 0;
+
+	/* set notifier */
+	ro->notifier.notifier_call	= raw_notifier;
+
+	register_netdevice_notifier(&ro->notifier);
+
+	return 0;
+}
+
+static int raw_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	struct flexray_raw_sock *ro;
+
+	if (!sk)
+		return 0;
+
+	ro = raw_sk(sk);
+
+	unregister_netdevice_notifier(&ro->notifier);
+
+	lock_sock(sk);
+
+	/* remove current filters & unregister */
+	if (ro->bound) {
+		if (ro->ifindex) {
+			struct net_device *dev;
+
+			dev = dev_get_by_index(&init_net, ro->ifindex);
+			if (dev) {
+				raw_disable_allfilters(dev, sk);
+				dev_put(dev);
+			}
+		} else
+			raw_disable_allfilters(NULL, sk);
+	}
+
+	ro->ifindex = 0;
+	ro->bound   = 0;
+
+	sock_orphan(sk);
+	sock->sk = NULL;
+
+	release_sock(sk);
+	sock_put(sk);
+
+	return 0;
+}
+
+static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
+{
+	struct sockaddr_flexray *addr = (struct sockaddr_flexray *)uaddr;
+	struct sock *sk = sock->sk;
+	struct flexray_raw_sock *ro = raw_sk(sk);
+	int ifindex;
+	int err = 0;
+	int notify_enetdown = 0;
+
+	if (len < sizeof(*addr))
+		return -EINVAL;
+
+	lock_sock(sk);
+
+	if (ro->bound && addr->flexray_ifindex == ro->ifindex)
+		goto out;
+
+	if (addr->flexray_ifindex) {
+		struct net_device *dev;
+
+		dev = dev_get_by_index(&init_net, addr->flexray_ifindex);
+		if (!dev) {
+			err = -ENODEV;
+			goto out;
+		}
+
+		if (dev->type != ARPHRD_FLEXRAY) {
+			dev_put(dev);
+			err = -ENODEV;
+			goto out;
+		}
+
+		if (!(dev->flags & IFF_UP))
+			notify_enetdown = 1;
+
+		ifindex = dev->ifindex;
+
+		/* filters set by default/setsockopt */
+		err = raw_enable_allfilters(dev, sk);
+
+		dev_put(dev);
+	} else {
+		ifindex = 0;
+
+		/* filters set by default/setsockopt */
+		err = raw_enable_allfilters(NULL, sk);
+	}
+
+	if (!err) {
+		if (ro->bound) {
+			/* unregister old filters */
+			if (ro->ifindex) {
+				struct net_device *dev;
+
+				dev = dev_get_by_index(&init_net, ro->ifindex);
+				if (dev) {
+					raw_disable_allfilters(dev, sk);
+					dev_put(dev);
+				}
+			} else
+				raw_disable_allfilters(NULL, sk);
+		}
+
+		ro->ifindex = ifindex;
+		ro->bound = 1;
+	}
+
+out:
+	release_sock(sk);
+
+	if (notify_enetdown) {
+		sk->sk_err = ENETDOWN;
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_error_report(sk);
+	}
+
+	return err;
+}
+
+static int raw_getname(struct socket *sock, struct sockaddr *uaddr,
+		       int *len, int peer)
+{
+	struct sockaddr_flexray *addr = (struct sockaddr_flexray *)uaddr;
+	struct sock *sk = sock->sk;
+	struct flexray_raw_sock *ro = raw_sk(sk);
+
+	if (peer)
+		return -EOPNOTSUPP;
+
+	memset(addr, 0, sizeof(*addr));
+	addr->flexray_family  = AF_FLEXRAY;
+	addr->flexray_ifindex = ro->ifindex;
+
+	*len = sizeof(*addr);
+
+	return 0;
+}
+
+static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
+		       struct msghdr *msg, size_t size)
+{
+	struct sock *sk = sock->sk;
+	struct flexray_raw_sock *ro = raw_sk(sk);
+	struct sk_buff *skb;
+	struct net_device *dev;
+	int ifindex;
+	int err;
+
+	if (msg->msg_name) {
+		struct sockaddr_flexray *addr =
+			(struct sockaddr_flexray *)msg->msg_name;
+
+		if (msg->msg_namelen < sizeof(*addr))
+			return -EINVAL;
+
+		if (addr->flexray_family != AF_FLEXRAY)
+			return -EINVAL;
+
+		ifindex = addr->flexray_ifindex;
+	} else
+		ifindex = ro->ifindex;
+
+	dev = dev_get_by_index(&init_net, ifindex);
+	if (!dev)
+		return -ENXIO;
+
+	skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
+				  &err);
+	if (!skb)
+		goto put_dev;
+
+	err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
+	if (err < 0)
+		goto free_skb;
+
+	sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
+
+	skb->dev = dev;
+	skb->sk  = sk;
+
+	err = flexray_send(skb);
+	if (err)
+		goto put_dev;
+
+	dev_put(dev);
+
+	return size;
+
+free_skb:
+	kfree_skb(skb);
+put_dev:
+	dev_put(dev);
+
+	return err;
+}
+
+static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
+		       struct msghdr *msg, size_t size, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sk_buff *skb;
+	int err = 0;
+	int noblock;
+
+	noblock =  flags & MSG_DONTWAIT;
+	flags   &= ~MSG_DONTWAIT;
+
+	skb = skb_recv_datagram(sk, flags, noblock, &err);
+	if (!skb)
+		return err;
+
+	if (size < skb->len)
+		msg->msg_flags |= MSG_TRUNC;
+	else
+		size = skb->len;
+
+	err = memcpy_toiovec(msg->msg_iov, skb->data, size);
+	if (err < 0) {
+		skb_free_datagram(sk, skb);
+		return err;
+	}
+
+	sock_recv_ts_and_drops(msg, sk, skb);
+
+	if (msg->msg_name) {
+		msg->msg_namelen = sizeof(struct sockaddr_flexray);
+		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+	}
+
+	/* assign the flags that have been recorded in raw_rcv() */
+	msg->msg_flags |= *(raw_flags(skb));
+
+	skb_free_datagram(sk, skb);
+
+	return size;
+}
+
+static const struct proto_ops raw_ops = {
+	.family		= PF_FLEXRAY,
+	.release	= raw_release,
+	.bind		= raw_bind,
+	.connect	= sock_no_connect,
+	.socketpair	= sock_no_socketpair,
+	.accept		= sock_no_accept,
+	.getname	= raw_getname,
+	.poll		= datagram_poll,
+	.ioctl		= flexray_ioctl,
+	.listen		= sock_no_listen,
+	.shutdown	= sock_no_shutdown,
+	.sendmsg	= raw_sendmsg,
+	.recvmsg	= raw_recvmsg,
+	.mmap		= sock_no_mmap,
+	.sendpage	= sock_no_sendpage,
+};
+
+static struct proto raw_proto __read_mostly = {
+	.name		= "FLEXRAY_RAW",
+	.owner		= THIS_MODULE,
+	.obj_size	= sizeof(struct flexray_raw_sock),
+	.init		= raw_init,
+};
+
+static const struct flexray_proto raw_flexray_proto = {
+	.type		= SOCK_RAW,
+	.protocol	= FLEXRAY_RAW,
+	.ops		= &raw_ops,
+	.prot		= &raw_proto,
+};
+
+static __init int raw_module_init(void)
+{
+	int err;
+
+	err = flexray_proto_register(&raw_flexray_proto);
+	if (err < 0)
+		pr_err("flexray: registration of raw protocol failed\n");
+
+	return err;
+}
+module_init(raw_module_init);
+
+static __exit void raw_module_exit(void)
+{
+	flexray_proto_unregister(&raw_flexray_proto);
+}
+module_exit(raw_module_exit);
+
+MODULE_DESCRIPTION("PF_FLEXRAY raw protocol");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Benedikt Spranger <b.spranger@...utronix.de>");
+MODULE_ALIAS("flexray-proto-1");
-- 
1.8.4.rc2

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists