netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] PhoNet protocols stack v2
@ 2008-09-22 15:45 Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 01/11] Phonet global definitions Rémi Denis-Courmont
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:45 UTC (permalink / raw)
  To: netdev

        Hello,

This patch series is the second attempt at support for PhoNet network protocol 
stack in the Linux kernel and trying to address various comments already 
received on the mailing list. This protocol is the primary interface to Nokia 
cellular modem engines. We are integrating it to the Linux kernel in order to 
support HSPA cellular data connectivity on the Maemo Software platform.

This patchset provides a "raw" datagram protocol as a starting point, and is 
based on the current net-next-2.6.

Any comments welcome.

-- 
Rémi Denis-Courmont
Maemo Software, Nokia Devices R&D

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/11] Phonet global definitions
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 02/11] Phonet: PF_PHONET protocol family support Rémi Denis-Courmont
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/linux/if_ether.h  |    1 +
 include/linux/if_phonet.h |   14 +++++
 include/linux/phonet.h    |  125 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/rtnetlink.h |    4 ++
 include/linux/socket.h    |    4 +-
 net/core/sock.c           |    9 ++-
 6 files changed, 153 insertions(+), 4 deletions(-)
 create mode 100644 include/linux/if_phonet.h
 create mode 100644 include/linux/phonet.h

diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 5028e0b..723a1c5 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -100,6 +100,7 @@
 #define ETH_P_ECONET	0x0018		/* Acorn Econet			*/
 #define ETH_P_HDLC	0x0019		/* HDLC frames			*/
 #define ETH_P_ARCNET	0x001A		/* 1A for ArcNet :-)            */
+#define ETH_P_PHONET	0x00F5		/* Nokia Phonet frames          */
 
 /*
  *	This is an Ethernet frame header.
diff --git a/include/linux/if_phonet.h b/include/linux/if_phonet.h
new file mode 100644
index 0000000..22df25f
--- /dev/null
+++ b/include/linux/if_phonet.h
@@ -0,0 +1,14 @@
+/*
+ * File: if_phonet.h
+ *
+ * Phonet interface kernel definitions
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ */
+
+#define PHONET_HEADER_LEN	8	/* Phonet header length */
+
+#define PHONET_MIN_MTU		6
+/* 6 bytes header + 65535 bytes payload */
+#define PHONET_MAX_MTU		65541
+#define PHONET_DEV_MTU		PHONET_MAX_MTU
diff --git a/include/linux/phonet.h b/include/linux/phonet.h
new file mode 100644
index 0000000..6a764f8
--- /dev/null
+++ b/include/linux/phonet.h
@@ -0,0 +1,125 @@
+/**
+ * file phonet.h
+ *
+ * Phonet sockets kernel interface
+ *
+ * Copyright (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef LINUX_PHONET_H
+#define LINUX_PHONET_H
+
+/* Automatic protocol selection */
+#define PN_PROTO_TRANSPORT	0
+/* Phonet datagram socket */
+#define PN_PROTO_PHONET		1
+#define PHONET_NPROTO		2
+
+#define PNADDR_ANY		0
+#define PNPORT_RESOURCE_ROUTING	0
+
+/* Phonet protocol header */
+struct phonethdr {
+	__u8	pn_rdev;
+	__u8	pn_sdev;
+	__u8	pn_res;
+	__be16	pn_length;
+	__u8	pn_robj;
+	__u8	pn_sobj;
+} __attribute__((packed));
+
+/* Phonet socket address structure */
+struct sockaddr_pn {
+	sa_family_t spn_family;
+	__u8 spn_obj;
+	__u8 spn_dev;
+	__u8 spn_resource;
+	__u8 spn_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - 3];
+} __attribute__ ((packed));
+
+static inline __u16 pn_object(__u8 addr, __u16 port)
+{
+	return (addr << 8) | (port & 0x3ff);
+}
+
+static inline __u8 pn_obj(__u16 handle)
+{
+	return handle & 0xff;
+}
+
+static inline __u8 pn_dev(__u16 handle)
+{
+	return handle >> 8;
+}
+
+static inline __u16 pn_port(__u16 handle)
+{
+	return handle & 0x3ff;
+}
+
+static inline __u8 pn_addr(__u16 handle)
+{
+	return (handle >> 8) & 0xfc;
+}
+
+static inline void pn_sockaddr_set_addr(struct sockaddr_pn *spn, __u8 addr)
+{
+	spn->spn_dev &= 0x03;
+	spn->spn_dev |= addr & 0xfc;
+}
+
+static inline void pn_sockaddr_set_port(struct sockaddr_pn *spn, __u16 port)
+{
+	spn->spn_dev &= 0xfc;
+	spn->spn_dev |= (port >> 8) & 0x03;
+	spn->spn_obj = port & 0xff;
+}
+
+static inline void pn_sockaddr_set_object(struct sockaddr_pn *spn,
+						__u16 handle)
+{
+	spn->spn_dev = pn_dev(handle);
+	spn->spn_obj = pn_obj(handle);
+}
+
+static inline void pn_sockaddr_set_resource(struct sockaddr_pn *spn,
+						__u8 resource)
+{
+	spn->spn_resource = resource;
+}
+
+static inline __u8 pn_sockaddr_get_addr(const struct sockaddr_pn *spn)
+{
+	return spn->spn_dev & 0xfc;
+}
+
+static inline __u16 pn_sockaddr_get_port(const struct sockaddr_pn *spn)
+{
+	return ((spn->spn_dev & 0x03) << 8) | spn->spn_obj;
+}
+
+static inline __u16 pn_sockaddr_get_object(const struct sockaddr_pn *spn)
+{
+	return pn_object(spn->spn_dev, spn->spn_obj);
+}
+
+static inline __u8 pn_sockaddr_get_resource(const struct sockaddr_pn *spn)
+{
+	return spn->spn_resource;
+}
+
+#endif
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index ca643b1..2b3d51c 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -582,6 +582,10 @@ enum rtnetlink_groups {
 #define RTNLGRP_IPV6_RULE	RTNLGRP_IPV6_RULE
 	RTNLGRP_ND_USEROPT,
 #define RTNLGRP_ND_USEROPT	RTNLGRP_ND_USEROPT
+	RTNLGRP_PHONET_IFADDR,
+#define RTNLGRP_PHONET_IFADDR	RTNLGRP_PHONET_IFADDR
+	RTNLGRP_PHONET_ROUTE,
+#define RTNLGRP_PHONET_ROUTE	RTNLGRP_PHONET_ROUTE
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index dc5086f..818ca33 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -190,7 +190,8 @@ struct ucred {
 #define AF_IUCV		32	/* IUCV sockets			*/
 #define AF_RXRPC	33	/* RxRPC sockets 		*/
 #define AF_ISDN		34	/* mISDN sockets 		*/
-#define AF_MAX		35	/* For now.. */
+#define AF_PHONET	35	/* Phonet sockets		*/
+#define AF_MAX		36	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
@@ -227,6 +228,7 @@ struct ucred {
 #define PF_IUCV		AF_IUCV
 #define PF_RXRPC	AF_RXRPC
 #define PF_ISDN		AF_ISDN
+#define PF_PHONET	AF_PHONET
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
diff --git a/net/core/sock.c b/net/core/sock.c
index 23b8b9d..2d358dd 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -154,7 +154,8 @@ static const char *af_family_key_strings[AF_MAX+1] = {
   "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE"  , "sk_lock-AF_LLC"      ,
   "sk_lock-27"       , "sk_lock-28"          , "sk_lock-AF_CAN"      ,
   "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
-  "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_MAX"
+  "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
+  "sk_lock-AF_MAX"
 };
 static const char *af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
@@ -168,7 +169,8 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_PPPOX" , "slock-AF_WANPIPE"  , "slock-AF_LLC"      ,
   "slock-27"       , "slock-28"          , "slock-AF_CAN"      ,
   "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
-  "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_MAX"
+  "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
+  "slock-AF_MAX"
 };
 static const char *af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
@@ -182,7 +184,8 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_PPPOX" , "clock-AF_WANPIPE"  , "clock-AF_LLC"      ,
   "clock-27"       , "clock-28"          , "clock-AF_CAN"      ,
   "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
-  "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_MAX"
+  "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
+  "clock-AF_MAX"
 };
 #endif
 
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/11] Phonet: PF_PHONET protocol family support
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 01/11] Phonet global definitions Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 03/11] Phonet: add CONFIG_PHONET Rémi Denis-Courmont
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

This is the basis for the Phonet protocol families, and introduces
the ETH_P_PHONET packet type and the PF_PHONET socket family.

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/net/phonet/phonet.h |   74 +++++++++++++++
 net/phonet/af_phonet.c      |  216 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 290 insertions(+), 0 deletions(-)
 create mode 100644 include/net/phonet/phonet.h
 create mode 100644 net/phonet/af_phonet.c

diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
new file mode 100644
index 0000000..c53f2ab
--- /dev/null
+++ b/include/net/phonet/phonet.h
@@ -0,0 +1,74 @@
+/*
+ * File: af_phonet.h
+ *
+ * Phonet sockets kernel definitions
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef AF_PHONET_H
+#define AF_PHONET_H
+
+/*
+ * The lower layers may not require more space, ever. Make sure it's
+ * enough.
+ */
+#define MAX_PHONET_HEADER	8
+
+static inline struct phonethdr *pn_hdr(struct sk_buff *skb)
+{
+	return (struct phonethdr *)skb_network_header(skb);
+}
+
+/*
+ * Get the other party's sockaddr from received skb. The skb begins
+ * with a Phonet header.
+ */
+static inline
+void pn_skb_get_src_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa)
+{
+	struct phonethdr *ph = pn_hdr(skb);
+	u16 obj = pn_object(ph->pn_sdev, ph->pn_sobj);
+
+	sa->spn_family = AF_PHONET;
+	pn_sockaddr_set_object(sa, obj);
+	pn_sockaddr_set_resource(sa, ph->pn_res);
+	memset(sa->spn_zero, 0, sizeof(sa->spn_zero));
+}
+
+static inline
+void pn_skb_get_dst_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa)
+{
+	struct phonethdr *ph = pn_hdr(skb);
+	u16 obj = pn_object(ph->pn_rdev, ph->pn_robj);
+
+	sa->spn_family = AF_PHONET;
+	pn_sockaddr_set_object(sa, obj);
+	pn_sockaddr_set_resource(sa, ph->pn_res);
+	memset(sa->spn_zero, 0, sizeof(sa->spn_zero));
+}
+
+/* Protocols in Phonet protocol family. */
+struct phonet_protocol {
+	struct proto		*prot;
+	int			sock_type;
+};
+
+int phonet_proto_register(int protocol, struct phonet_protocol *pp);
+void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
+
+#endif
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
new file mode 100644
index 0000000..0cfea9b
--- /dev/null
+++ b/net/phonet/af_phonet.c
@@ -0,0 +1,216 @@
+/*
+ * File: af_phonet.c
+ *
+ * Phonet protocols family
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+ * Original author: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+#include <net/sock.h>
+
+#include <linux/if_phonet.h>
+#include <linux/phonet.h>
+#include <net/phonet/phonet.h>
+
+static struct net_proto_family phonet_proto_family;
+static struct phonet_protocol *phonet_proto_get(int protocol);
+static inline void phonet_proto_put(struct phonet_protocol *pp);
+
+/* protocol family functions */
+
+static int pn_socket_create(struct net *net, struct socket *sock, int protocol)
+{
+	struct phonet_protocol *pnp;
+	int err;
+
+	if (net != &init_net)
+		return -EAFNOSUPPORT;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (protocol == 0) {
+		/* Default protocol selection */
+		switch (sock->type) {
+		case SOCK_DGRAM:
+			protocol = PN_PROTO_PHONET;
+			break;
+		default:
+			return -EPROTONOSUPPORT;
+		}
+	}
+
+	pnp = phonet_proto_get(protocol);
+	if (pnp == NULL)
+		return -EPROTONOSUPPORT;
+	if (sock->type != pnp->sock_type) {
+		err = -EPROTONOSUPPORT;
+		goto out;
+	}
+
+	/* TODO: create and init the struct sock */
+	err = -EPROTONOSUPPORT;
+
+out:
+	phonet_proto_put(pnp);
+	return err;
+}
+
+static struct net_proto_family phonet_proto_family = {
+	.family = AF_PHONET,
+	.create = pn_socket_create,
+	.owner = THIS_MODULE,
+};
+
+/* packet type functions */
+
+/*
+ * Stuff received packets to associated sockets.
+ * On error, returns non-zero and releases the skb.
+ */
+static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
+			struct packet_type *pkttype,
+			struct net_device *orig_dev)
+{
+	struct phonethdr *ph;
+	struct sockaddr_pn sa;
+	u16 len;
+
+	if (dev_net(dev) != &init_net)
+		goto out;
+
+	/* check we have at least a full Phonet header */
+	if (!pskb_pull(skb, sizeof(struct phonethdr)))
+		goto out;
+
+	/* check that the advertised length is correct */
+	ph = pn_hdr(skb);
+	len = get_unaligned_be16(&ph->pn_length);
+	if (len < 2)
+		goto out;
+	len -= 2;
+	if ((len > skb->len) || pskb_trim(skb, len))
+		goto out;
+	skb_reset_transport_header(skb);
+
+	pn_skb_get_dst_sockaddr(skb, &sa);
+	if (pn_sockaddr_get_addr(&sa) == 0)
+		goto out; /* currently, we cannot be device 0 */
+
+	/* TODO: put packets to sockets backlog */
+
+out:
+	kfree_skb(skb);
+	return NET_RX_DROP;
+}
+
+static struct packet_type phonet_packet_type = {
+	.type = __constant_htons(ETH_P_PHONET),
+	.dev = NULL,
+	.func = phonet_rcv,
+};
+
+/* Transport protocol registration */
+static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
+static DEFINE_SPINLOCK(proto_tab_lock);
+
+int __init_or_module phonet_proto_register(int protocol,
+						struct phonet_protocol *pp)
+{
+	int err = 0;
+
+	if (protocol >= PHONET_NPROTO)
+		return -EINVAL;
+
+	err = proto_register(pp->prot, 1);
+	if (err)
+		return err;
+
+	spin_lock(&proto_tab_lock);
+	if (proto_tab[protocol])
+		err = -EBUSY;
+	else
+		proto_tab[protocol] = pp;
+	spin_unlock(&proto_tab_lock);
+
+	return err;
+}
+EXPORT_SYMBOL(phonet_proto_register);
+
+void phonet_proto_unregister(int protocol, struct phonet_protocol *pp)
+{
+	spin_lock(&proto_tab_lock);
+	BUG_ON(proto_tab[protocol] != pp);
+	proto_tab[protocol] = NULL;
+	spin_unlock(&proto_tab_lock);
+	proto_unregister(pp->prot);
+}
+EXPORT_SYMBOL(phonet_proto_unregister);
+
+static struct phonet_protocol *phonet_proto_get(int protocol)
+{
+	struct phonet_protocol *pp;
+
+	if (protocol >= PHONET_NPROTO)
+		return NULL;
+
+	spin_lock(&proto_tab_lock);
+	pp = proto_tab[protocol];
+	if (pp && !try_module_get(pp->prot->owner))
+		pp = NULL;
+	spin_unlock(&proto_tab_lock);
+
+	return pp;
+}
+
+static inline void phonet_proto_put(struct phonet_protocol *pp)
+{
+	module_put(pp->prot->owner);
+}
+
+/* Module registration */
+static int __init phonet_init(void)
+{
+	int err;
+
+	err = sock_register(&phonet_proto_family);
+	if (err) {
+		printk(KERN_ALERT
+			"phonet protocol family initialization failed\n");
+		return err;
+	}
+
+	dev_add_pack(&phonet_packet_type);
+	return 0;
+}
+
+static void __exit phonet_exit(void)
+{
+	sock_unregister(AF_PHONET);
+	dev_remove_pack(&phonet_packet_type);
+}
+
+module_init(phonet_init);
+module_exit(phonet_exit);
+MODULE_DESCRIPTION("Phonet protocol stack for Linux");
+MODULE_LICENSE("GPL");
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/11] Phonet: add CONFIG_PHONET
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 01/11] Phonet global definitions Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 02/11] Phonet: PF_PHONET protocol family support Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 04/11] Phonet: network device and address handling Rémi Denis-Courmont
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 net/Kconfig         |    1 +
 net/Makefile        |    1 +
 net/phonet/Kconfig  |   16 ++++++++++++++++
 net/phonet/Makefile |    4 ++++
 4 files changed, 22 insertions(+), 0 deletions(-)
 create mode 100644 net/phonet/Kconfig
 create mode 100644 net/phonet/Makefile

diff --git a/net/Kconfig b/net/Kconfig
index d87de48..9103a16 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -232,6 +232,7 @@ source "net/can/Kconfig"
 source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
 source "net/rxrpc/Kconfig"
+source "net/phonet/Kconfig"
 
 config FIB_RULES
 	bool
diff --git a/net/Makefile b/net/Makefile
index 4f43e7f..acaf819 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_AF_RXRPC)		+= rxrpc/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_DECNET)		+= decnet/
 obj-$(CONFIG_ECONET)		+= econet/
+obj-$(CONFIG_PHONET)		+= phonet/
 ifneq ($(CONFIG_VLAN_8021Q),)
 obj-y				+= 8021q/
 endif
diff --git a/net/phonet/Kconfig b/net/phonet/Kconfig
new file mode 100644
index 0000000..51a5669
--- /dev/null
+++ b/net/phonet/Kconfig
@@ -0,0 +1,16 @@
+#
+# Phonet protocol
+#
+
+config PHONET
+	tristate "Phonet protocols family"
+	help
+	  The Phone Network protocol (PhoNet) is a packet-oriented
+	  communication protocol developped by Nokia for use with its modems.
+
+	  This is required for Maemo to use cellular data connectivity (if
+	  supported). It can also be used to control Nokia phones
+	  from a Linux computer, although AT commands may be easier to use.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called phonet. If unsure, say N.
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
new file mode 100644
index 0000000..5dbff68
--- /dev/null
+++ b/net/phonet/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_PHONET) += phonet.o
+
+phonet-objs := \
+	af_phonet.o
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/11] Phonet: network device and address handling
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (2 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 03/11] Phonet: add CONFIG_PHONET Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 05/11] Phonet: Netlink interface Rémi Denis-Courmont
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

This provides support for adding Phonet addresses to and removing
Phonet addresses from network devices.

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/net/phonet/pn_dev.h |   50 ++++++++++
 net/phonet/Makefile         |    1 +
 net/phonet/af_phonet.c      |    3 +
 net/phonet/pn_dev.c         |  208 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 262 insertions(+), 0 deletions(-)
 create mode 100644 include/net/phonet/pn_dev.h
 create mode 100644 net/phonet/pn_dev.c

diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h
new file mode 100644
index 0000000..bbd2a83
--- /dev/null
+++ b/include/net/phonet/pn_dev.h
@@ -0,0 +1,50 @@
+/*
+ * File: pn_dev.h
+ *
+ * Phonet network device
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef PN_DEV_H
+#define PN_DEV_H
+
+struct phonet_device_list {
+	struct list_head list;
+	spinlock_t lock;
+};
+
+extern struct phonet_device_list pndevs;
+
+struct phonet_device {
+	struct list_head list;
+	struct net_device *netdev;
+	DECLARE_BITMAP(addrs, 64);
+};
+
+void phonet_device_init(void);
+void phonet_device_exit(void);
+struct net_device *phonet_device_get(struct net *net);
+
+int phonet_address_add(struct net_device *dev, u8 addr);
+int phonet_address_del(struct net_device *dev, u8 addr);
+u8 phonet_address_get(struct net_device *dev, u8 addr);
+int phonet_address_lookup(u8 addr);
+
+#define PN_NO_ADDR	0xff
+
+#endif
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
index 5dbff68..980a386 100644
--- a/net/phonet/Makefile
+++ b/net/phonet/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PHONET) += phonet.o
 
 phonet-objs := \
+	pn_dev.o \
 	af_phonet.o
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 0cfea9b..a8ba6f1 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -31,6 +31,7 @@
 #include <linux/if_phonet.h>
 #include <linux/phonet.h>
 #include <net/phonet/phonet.h>
+#include <net/phonet/pn_dev.h>
 
 static struct net_proto_family phonet_proto_family;
 static struct phonet_protocol *phonet_proto_get(int protocol);
@@ -200,6 +201,7 @@ static int __init phonet_init(void)
 		return err;
 	}
 
+	phonet_device_init();
 	dev_add_pack(&phonet_packet_type);
 	return 0;
 }
@@ -208,6 +210,7 @@ static void __exit phonet_exit(void)
 {
 	sock_unregister(AF_PHONET);
 	dev_remove_pack(&phonet_packet_type);
+	phonet_device_exit();
 }
 
 module_init(phonet_init);
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
new file mode 100644
index 0000000..53be9fc
--- /dev/null
+++ b/net/phonet/pn_dev.c
@@ -0,0 +1,208 @@
+/*
+ * File: pn_dev.c
+ *
+ * Phonet network device
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+ * Original author: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/phonet.h>
+#include <net/sock.h>
+#include <net/phonet/pn_dev.h>
+
+/* when accessing, remember to lock with spin_lock(&pndevs.lock); */
+struct phonet_device_list pndevs = {
+	.list = LIST_HEAD_INIT(pndevs.list),
+	.lock = __SPIN_LOCK_UNLOCKED(pndevs.lock),
+};
+
+/* Allocate new Phonet device. */
+static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
+{
+	struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC);
+	if (pnd == NULL)
+		return NULL;
+	pnd->netdev = dev;
+	bitmap_zero(pnd->addrs, 64);
+
+	list_add(&pnd->list, &pndevs.list);
+	return pnd;
+}
+
+static struct phonet_device *__phonet_get(struct net_device *dev)
+{
+	struct phonet_device *pnd;
+
+	list_for_each_entry(pnd, &pndevs.list, list) {
+		if (pnd->netdev == dev)
+			return pnd;
+	}
+	return NULL;
+}
+
+static void __phonet_device_free(struct phonet_device *pnd)
+{
+	list_del(&pnd->list);
+	kfree(pnd);
+}
+
+struct net_device *phonet_device_get(struct net *net)
+{
+	struct phonet_device *pnd;
+	struct net_device *dev;
+
+	spin_lock_bh(&pndevs.lock);
+	list_for_each_entry(pnd, &pndevs.list, list) {
+		dev = pnd->netdev;
+		BUG_ON(!dev);
+
+		if (dev_net(dev) == net &&
+			(dev->reg_state == NETREG_REGISTERED) &&
+			((pnd->netdev->flags & IFF_UP)) == IFF_UP)
+			break;
+		dev = NULL;
+	}
+	if (dev)
+		dev_hold(dev);
+	spin_unlock_bh(&pndevs.lock);
+	return dev;
+}
+
+int phonet_address_add(struct net_device *dev, u8 addr)
+{
+	struct phonet_device *pnd;
+	int err = 0;
+
+	spin_lock_bh(&pndevs.lock);
+	/* Find or create Phonet-specific device data */
+	pnd = __phonet_get(dev);
+	if (pnd == NULL)
+		pnd = __phonet_device_alloc(dev);
+	if (unlikely(pnd == NULL))
+		err = -ENOMEM;
+	else if (test_and_set_bit(addr >> 2, pnd->addrs))
+		err = -EEXIST;
+	spin_unlock_bh(&pndevs.lock);
+	return err;
+}
+
+int phonet_address_del(struct net_device *dev, u8 addr)
+{
+	struct phonet_device *pnd;
+	int err = 0;
+
+	spin_lock_bh(&pndevs.lock);
+	pnd = __phonet_get(dev);
+	if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs))
+		err = -EADDRNOTAVAIL;
+	if (bitmap_empty(pnd->addrs, 64))
+		__phonet_device_free(pnd);
+	spin_unlock_bh(&pndevs.lock);
+	return err;
+}
+
+/* Gets a source address toward a destination, through a interface. */
+u8 phonet_address_get(struct net_device *dev, u8 addr)
+{
+	struct phonet_device *pnd;
+
+	spin_lock_bh(&pndevs.lock);
+	pnd = __phonet_get(dev);
+	if (pnd) {
+		BUG_ON(bitmap_empty(pnd->addrs, 64));
+
+		/* Use same source address as destination, if possible */
+		if (!test_bit(addr >> 2, pnd->addrs))
+			addr = find_first_bit(pnd->addrs, 64) << 2;
+	} else
+		addr = PN_NO_ADDR;
+	spin_unlock_bh(&pndevs.lock);
+	return addr;
+}
+
+int phonet_address_lookup(u8 addr)
+{
+	struct phonet_device *pnd;
+
+	spin_lock_bh(&pndevs.lock);
+	list_for_each_entry(pnd, &pndevs.list, list) {
+		/* Don't allow unregistering devices! */
+		if ((pnd->netdev->reg_state != NETREG_REGISTERED) ||
+				((pnd->netdev->flags & IFF_UP)) != IFF_UP)
+			continue;
+
+		if (test_bit(addr >> 2, pnd->addrs)) {
+			spin_unlock_bh(&pndevs.lock);
+			return 0;
+		}
+	}
+	spin_unlock_bh(&pndevs.lock);
+	return -EADDRNOTAVAIL;
+}
+
+/* notify Phonet of device events */
+static int phonet_device_notify(struct notifier_block *me, unsigned long what,
+				void *arg)
+{
+	struct net_device *dev = arg;
+
+	if (what == NETDEV_UNREGISTER) {
+		struct phonet_device *pnd;
+
+		/* Destroy phonet-specific device data */
+		spin_lock_bh(&pndevs.lock);
+		pnd = __phonet_get(dev);
+		if (pnd)
+			__phonet_device_free(pnd);
+		spin_unlock_bh(&pndevs.lock);
+	}
+	return 0;
+
+}
+
+static struct notifier_block phonet_device_notifier = {
+	.notifier_call = phonet_device_notify,
+	.priority = 0,
+};
+
+/* Initialize Phonet devices list */
+void phonet_device_init(void)
+{
+	register_netdevice_notifier(&phonet_device_notifier);
+}
+
+void phonet_device_exit(void)
+{
+	struct phonet_device *pnd, *n;
+
+	rtnl_unregister_all(PF_PHONET);
+	rtnl_lock();
+	spin_lock_bh(&pndevs.lock);
+
+	list_for_each_entry_safe(pnd, n, &pndevs.list, list)
+		__phonet_device_free(pnd);
+
+	spin_unlock_bh(&pndevs.lock);
+	rtnl_unlock();
+	unregister_netdevice_notifier(&phonet_device_notifier);
+}
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/11] Phonet: Netlink interface
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (3 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 04/11] Phonet: network device and address handling Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-23 12:10   ` Thomas Graf
  2008-09-22 15:47 ` [PATCH 06/11] Phonet: common socket glue Rémi Denis-Courmont
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

This provides support for configuring Phonet addresses, notifying
Phonet configuration changes, and dumping the configuration.

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/net/phonet/phonet.h |    1 +
 net/phonet/Makefile         |    1 +
 net/phonet/af_phonet.c      |    1 +
 net/phonet/pn_netlink.c     |  186 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 189 insertions(+), 0 deletions(-)
 create mode 100644 net/phonet/pn_netlink.c

diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index c53f2ab..8b77794 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -71,4 +71,5 @@ struct phonet_protocol {
 int phonet_proto_register(int protocol, struct phonet_protocol *pp);
 void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
 
+void phonet_netlink_register(void);
 #endif
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
index 980a386..4143c3e 100644
--- a/net/phonet/Makefile
+++ b/net/phonet/Makefile
@@ -2,4 +2,5 @@ obj-$(CONFIG_PHONET) += phonet.o
 
 phonet-objs := \
 	pn_dev.o \
+	pn_netlink.o \
 	af_phonet.o
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index a8ba6f1..5c729ba 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -203,6 +203,7 @@ static int __init phonet_init(void)
 
 	phonet_device_init();
 	dev_add_pack(&phonet_packet_type);
+	phonet_netlink_register();
 	return 0;
 }
 
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
new file mode 100644
index 0000000..b1ea19a
--- /dev/null
+++ b/net/phonet/pn_netlink.c
@@ -0,0 +1,186 @@
+/*
+ * File: pn_netlink.c
+ *
+ * Phonet netlink interface
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+ * Original author: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/netlink.h>
+#include <linux/phonet.h>
+#include <net/sock.h>
+#include <net/phonet/pn_dev.h>
+
+static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
+		     u32 pid, u32 seq, int event);
+
+static void rtmsg_notify(int event, struct net_device *dev, u8 addr)
+{
+	struct sk_buff *skb;
+	int err = -ENOBUFS;
+
+	skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
+			nla_total_size(1), GFP_KERNEL);
+	if (skb == NULL)
+		goto errout;
+	err = fill_addr(skb, dev, addr, 0, 0, event);
+	if (err < 0) {
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
+	err = rtnl_notify(skb, dev_net(dev), 0,
+			  RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL);
+errout:
+	if (err < 0)
+		rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err);
+}
+
+static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
+{
+	struct rtattr **rta = attr;
+	struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
+	struct net_device *dev;
+	int err;
+	u8 pnaddr;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ASSERT_RTNL();
+
+	if (rta[IFA_LOCAL - 1] == NULL)
+		return -EINVAL;
+
+	dev = __dev_get_by_index(&init_net, ifm->ifa_index);
+	if (dev == NULL)
+		return -ENODEV;
+
+	if (ifm->ifa_prefixlen > 0)
+		return -EINVAL;
+
+	memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);
+
+	err = phonet_address_add(dev, pnaddr);
+	if (!err)
+		rtmsg_notify(RTM_NEWADDR, dev, pnaddr);
+	return err;
+}
+
+static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
+{
+	struct rtattr **rta = attr;
+	struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
+	struct net_device *dev;
+	int err;
+	u8 pnaddr;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ASSERT_RTNL();
+
+	if (rta[IFA_LOCAL - 1] == NULL)
+		return -EINVAL;
+
+	dev = __dev_get_by_index(&init_net, ifm->ifa_index);
+	if (dev == NULL)
+		return -ENODEV;
+
+	if (ifm->ifa_prefixlen > 0)
+		return -EADDRNOTAVAIL;
+
+	memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);
+
+	err = phonet_address_del(dev, pnaddr);
+	if (!err)
+		rtmsg_notify(RTM_DELADDR, dev, pnaddr);
+	return err;
+}
+
+static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
+			u32 pid, u32 seq, int event)
+{
+	struct ifaddrmsg *ifm;
+	struct nlmsghdr *nlh;
+	unsigned int orig_len = skb->len;
+
+	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg));
+	ifm = NLMSG_DATA(nlh);
+	ifm->ifa_family = AF_PHONET;
+	ifm->ifa_prefixlen = 0;
+	ifm->ifa_flags = IFA_F_PERMANENT;
+	ifm->ifa_scope = RT_SCOPE_HOST;
+	ifm->ifa_index = dev->ifindex;
+	RTA_PUT(skb, IFA_LOCAL, 1, &addr);
+	nlh->nlmsg_len = skb->len - orig_len;
+
+	return 0;
+
+nlmsg_failure:
+rtattr_failure:
+	skb_trim(skb, orig_len);
+
+	return -1;
+}
+
+static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct phonet_device *pnd;
+	int dev_idx = 0, dev_start_idx = cb->args[0];
+	int addr_idx = 0, addr_start_idx = cb->args[1];
+
+	spin_lock_bh(&pndevs.lock);
+	list_for_each_entry(pnd, &pndevs.list, list) {
+		u8 addr;
+
+		if (dev_idx > dev_start_idx)
+			addr_start_idx = 0;
+		if (dev_idx++ < dev_start_idx)
+			continue;
+
+		addr_idx = 0;
+		for (addr = find_first_bit(pnd->addrs, 64); addr < 64;
+			addr = find_next_bit(pnd->addrs, 64, 1+addr)) {
+			if (addr_idx++ < addr_start_idx)
+				continue;
+
+			if (fill_addr(skb, pnd->netdev, addr << 2,
+					 NETLINK_CB(cb->skb).pid,
+					cb->nlh->nlmsg_seq, RTM_NEWADDR))
+				goto out;
+		}
+	}
+
+out:
+	spin_unlock_bh(&pndevs.lock);
+	cb->args[0] = dev_idx;
+	cb->args[1] = addr_idx;
+
+	return skb->len;
+}
+
+void __init phonet_netlink_register(void)
+{
+	rtnl_register(PF_PHONET, RTM_NEWADDR, newaddr_doit, NULL);
+	rtnl_register(PF_PHONET, RTM_DELADDR, deladdr_doit, NULL);
+	rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
+}
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/11] Phonet: common socket glue
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (4 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 05/11] Phonet: Netlink interface Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 07/11] Phonet: Phonet datagram transport protocol Rémi Denis-Courmont
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

This provides the socket API for the Phonet protocols family.

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/linux/phonet.h      |    3 +
 include/net/phonet/phonet.h |   23 +++
 net/phonet/Makefile         |    1 +
 net/phonet/af_phonet.c      |   28 ++++-
 net/phonet/socket.c         |  311 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 363 insertions(+), 3 deletions(-)
 create mode 100644 net/phonet/socket.c

diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index 6a764f8..001c0e6 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -32,6 +32,9 @@
 #define PNADDR_ANY		0
 #define PNPORT_RESOURCE_ROUTING	0
 
+/* ioctls */
+#define SIOCPNGETOBJECT		(SIOCPROTOPRIVATE + 0)
+
 /* Phonet protocol header */
 struct phonethdr {
 	__u8	pn_rdev;
diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index 8b77794..2ae5cbb 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -29,6 +29,28 @@
  */
 #define MAX_PHONET_HEADER	8
 
+/*
+ * Every Phonet* socket has this structure first in its
+ * protocol-specific structure under name c.
+ */
+struct pn_sock {
+	struct sock	sk;
+	u16		sobject;
+	u8		resource;
+};
+
+static inline struct pn_sock *pn_sk(struct sock *sk)
+{
+	return (struct pn_sock *)sk;
+}
+
+extern const struct proto_ops phonet_dgram_ops;
+
+struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa);
+void pn_sock_hash(struct sock *sk);
+void pn_sock_unhash(struct sock *sk);
+int pn_sock_get_port(struct sock *sk, unsigned short sport);
+
 static inline struct phonethdr *pn_hdr(struct sk_buff *skb)
 {
 	return (struct phonethdr *)skb_network_header(skb);
@@ -64,6 +86,7 @@ void pn_skb_get_dst_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa)
 
 /* Protocols in Phonet protocol family. */
 struct phonet_protocol {
+	const struct proto_ops	*ops;
 	struct proto		*prot;
 	int			sock_type;
 };
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
index 4143c3e..c1d671d 100644
--- a/net/phonet/Makefile
+++ b/net/phonet/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_PHONET) += phonet.o
 phonet-objs := \
 	pn_dev.o \
 	pn_netlink.o \
+	socket.o \
 	af_phonet.o
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 5c729ba..ba54d53 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -41,6 +41,8 @@ static inline void phonet_proto_put(struct phonet_protocol *pp);
 
 static int pn_socket_create(struct net *net, struct socket *sock, int protocol)
 {
+	struct sock *sk;
+	struct pn_sock *pn;
 	struct phonet_protocol *pnp;
 	int err;
 
@@ -69,8 +71,22 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol)
 		goto out;
 	}
 
-	/* TODO: create and init the struct sock */
-	err = -EPROTONOSUPPORT;
+	sk = sk_alloc(net, PF_PHONET, GFP_KERNEL, pnp->prot);
+	if (sk == NULL) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	sock_init_data(sock, sk);
+	sock->state = SS_UNCONNECTED;
+	sock->ops = pnp->ops;
+	sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+	sk->sk_protocol = protocol;
+	pn = pn_sk(sk);
+	pn->sobject = 0;
+	pn->resource = 0;
+	sk->sk_prot->init(sk);
+	err = 0;
 
 out:
 	phonet_proto_put(pnp);
@@ -94,6 +110,7 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
 			struct net_device *orig_dev)
 {
 	struct phonethdr *ph;
+	struct sock *sk;
 	struct sockaddr_pn sa;
 	u16 len;
 
@@ -118,7 +135,12 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
 	if (pn_sockaddr_get_addr(&sa) == 0)
 		goto out; /* currently, we cannot be device 0 */
 
-	/* TODO: put packets to sockets backlog */
+	sk = pn_find_sock_by_sa(&sa);
+	if (sk == NULL)
+		goto out;
+
+	/* Push data to the socket (or other sockets connected to it). */
+	return sk_receive_skb(sk, skb, 0);
 
 out:
 	kfree_skb(skb);
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
new file mode 100644
index 0000000..99a4945
--- /dev/null
+++ b/net/phonet/socket.c
@@ -0,0 +1,311 @@
+/*
+ * File: socket.c
+ *
+ * Phonet sockets
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+ * Original author: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/net.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+
+#include <linux/phonet.h>
+#include <net/phonet/phonet.h>
+#include <net/phonet/pn_dev.h>
+
+static int pn_socket_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+
+	if (sk) {
+		sock->sk = NULL;
+		sk->sk_prot->close(sk, 0);
+	}
+	return 0;
+}
+
+static struct  {
+	struct hlist_head hlist;
+	spinlock_t lock;
+} pnsocks = {
+	.hlist = HLIST_HEAD_INIT,
+	.lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock),
+};
+
+/*
+ * Find address based on socket address, match only certain fields.
+ * Also grab sock if it was found. Remember to sock_put it later.
+ */
+struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn)
+{
+	struct hlist_node *node;
+	struct sock *sknode;
+	struct sock *rval = NULL;
+	u16 obj = pn_sockaddr_get_object(spn);
+	u8 res = spn->spn_resource;
+
+	spin_lock_bh(&pnsocks.lock);
+
+	sk_for_each(sknode, node, &pnsocks.hlist) {
+		struct pn_sock *pn = pn_sk(sknode);
+		BUG_ON(!pn->sobject); /* unbound socket */
+
+		if (pn_port(obj)) {
+			/* Look up socket by port */
+			if (pn_port(pn->sobject) != pn_port(obj))
+				continue;
+		} else {
+			/* If port is zero, look up by resource */
+			if (pn->resource != res)
+				continue;
+		}
+		if (pn_addr(pn->sobject)
+		 && pn_addr(pn->sobject) != pn_addr(obj))
+			continue;
+
+		rval = sknode;
+		sock_hold(sknode);
+		break;
+	}
+
+	spin_unlock_bh(&pnsocks.lock);
+
+	return rval;
+
+}
+
+void pn_sock_hash(struct sock *sk)
+{
+	spin_lock_bh(&pnsocks.lock);
+	sk_add_node(sk, &pnsocks.hlist);
+	spin_unlock_bh(&pnsocks.lock);
+}
+EXPORT_SYMBOL(pn_sock_hash);
+
+void pn_sock_unhash(struct sock *sk)
+{
+	spin_lock_bh(&pnsocks.lock);
+	sk_del_node_init(sk);
+	spin_unlock_bh(&pnsocks.lock);
+}
+EXPORT_SYMBOL(pn_sock_unhash);
+
+static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
+{
+	struct sock *sk = sock->sk;
+	struct pn_sock *pn = pn_sk(sk);
+	struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
+	int err;
+	u16 handle;
+	u8 saddr;
+
+	if (sk->sk_prot->bind)
+		return sk->sk_prot->bind(sk, addr, len);
+
+	if (len < sizeof(struct sockaddr_pn))
+		return -EINVAL;
+	if (spn->spn_family != AF_PHONET)
+		return -EAFNOSUPPORT;
+
+	handle = pn_sockaddr_get_object((struct sockaddr_pn *)addr);
+	saddr = pn_addr(handle);
+	if (saddr && phonet_address_lookup(saddr))
+		return -EADDRNOTAVAIL;
+
+	lock_sock(sk);
+	if (sk->sk_state != TCP_CLOSE || pn_port(pn->sobject)) {
+		err = -EINVAL; /* attempt to rebind */
+		goto out;
+	}
+	err = sk->sk_prot->get_port(sk, pn_port(handle));
+	if (err)
+		goto out;
+
+	/* get_port() sets the port, bind() sets the address if applicable */
+	pn->sobject = pn_object(saddr, pn_port(pn->sobject));
+	pn->resource = spn->spn_resource;
+
+	/* Enable RX on the socket */
+	sk->sk_prot->hash(sk);
+out:
+	release_sock(sk);
+	return err;
+}
+
+static int pn_socket_autobind(struct socket *sock)
+{
+	struct sockaddr_pn sa;
+	int err;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.spn_family = AF_PHONET;
+	err = pn_socket_bind(sock, (struct sockaddr *)&sa,
+				sizeof(struct sockaddr_pn));
+	if (err != -EINVAL)
+		return err;
+	BUG_ON(!pn_port(pn_sk(sock->sk)->sobject));
+	return 0; /* socket was already bound */
+}
+
+static int pn_socket_getname(struct socket *sock, struct sockaddr *addr,
+				int *sockaddr_len, int peer)
+{
+	struct sock *sk = sock->sk;
+	struct pn_sock *pn = pn_sk(sk);
+
+	memset(addr, 0, sizeof(struct sockaddr_pn));
+	addr->sa_family = AF_PHONET;
+	if (!peer) /* Race with bind() here is userland's problem. */
+		pn_sockaddr_set_object((struct sockaddr_pn *)addr,
+					pn->sobject);
+
+	*sockaddr_len = sizeof(struct sockaddr_pn);
+	return 0;
+}
+
+static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
+				unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+	struct pn_sock *pn = pn_sk(sk);
+
+	if (cmd == SIOCPNGETOBJECT) {
+		struct net_device *dev;
+		u16 handle;
+		u8 saddr;
+
+		if (get_user(handle, (__u16 __user *)arg))
+			return -EFAULT;
+
+		lock_sock(sk);
+		if (sk->sk_bound_dev_if)
+			dev = dev_get_by_index(sock_net(sk),
+						sk->sk_bound_dev_if);
+		else
+			dev = phonet_device_get(sock_net(sk));
+		if (dev && (dev->flags & IFF_UP))
+			saddr = phonet_address_get(dev, pn_addr(handle));
+		else
+			saddr = PN_NO_ADDR;
+		release_sock(sk);
+
+		if (dev)
+			dev_put(dev);
+		if (saddr == PN_NO_ADDR)
+			return -EHOSTUNREACH;
+
+		handle = pn_object(saddr, pn_port(pn->sobject));
+		return put_user(handle, (__u16 __user *)arg);
+	}
+
+	return sk->sk_prot->ioctl(sk, cmd, arg);
+}
+
+static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock,
+				struct msghdr *m, size_t total_len)
+{
+	struct sock *sk = sock->sk;
+
+	if (pn_socket_autobind(sock))
+		return -EAGAIN;
+
+	return sk->sk_prot->sendmsg(iocb, sk, m, total_len);
+}
+
+const struct proto_ops phonet_dgram_ops = {
+	.family		= AF_PHONET,
+	.owner		= THIS_MODULE,
+	.release	= pn_socket_release,
+	.bind		= pn_socket_bind,
+	.connect	= sock_no_connect,
+	.socketpair	= sock_no_socketpair,
+	.accept		= sock_no_accept,
+	.getname	= pn_socket_getname,
+	.poll		= datagram_poll,
+	.ioctl		= pn_socket_ioctl,
+	.listen		= sock_no_listen,
+	.shutdown	= sock_no_shutdown,
+	.setsockopt	= sock_no_setsockopt,
+	.getsockopt	= sock_no_getsockopt,
+#ifdef CONFIG_COMPAT
+	.compat_setsockopt = sock_no_setsockopt,
+	.compat_getsockopt = sock_no_getsockopt,
+#endif
+	.sendmsg	= pn_socket_sendmsg,
+	.recvmsg	= sock_common_recvmsg,
+	.mmap		= sock_no_mmap,
+	.sendpage	= sock_no_sendpage,
+};
+
+static DEFINE_MUTEX(port_mutex);
+
+/* allocate port for a socket */
+int pn_sock_get_port(struct sock *sk, unsigned short sport)
+{
+	static int port_cur;
+	struct pn_sock *pn = pn_sk(sk);
+	struct sockaddr_pn try_sa;
+	struct sock *tmpsk;
+
+	memset(&try_sa, 0, sizeof(struct sockaddr_pn));
+	try_sa.spn_family = AF_PHONET;
+
+	mutex_lock(&port_mutex);
+
+	if (!sport) {
+		/* search free port */
+		int port, pmin = 0x40, pmax = 0x7f;
+
+		for (port = pmin; port <= pmax; port++) {
+			port_cur++;
+			if (port_cur < pmin || port_cur > pmax)
+				port_cur = pmin;
+
+			pn_sockaddr_set_port(&try_sa, port_cur);
+			tmpsk = pn_find_sock_by_sa(&try_sa);
+			if (tmpsk == NULL) {
+				sport = port_cur;
+				goto found;
+			} else
+				sock_put(tmpsk);
+		}
+	} else {
+		/* try to find specific port */
+		pn_sockaddr_set_port(&try_sa, sport);
+		tmpsk = pn_find_sock_by_sa(&try_sa);
+		if (tmpsk == NULL)
+			/* No sock there! We can use that port... */
+			goto found;
+		else
+			sock_put(tmpsk);
+	}
+	mutex_unlock(&port_mutex);
+
+	/* the port must be in use already */
+	return -EADDRINUSE;
+
+found:
+	mutex_unlock(&port_mutex);
+	pn->sobject = pn_object(pn_addr(pn->sobject), sport);
+	return 0;
+}
+EXPORT_SYMBOL(pn_sock_get_port);
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/11] Phonet: Phonet datagram transport protocol
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (5 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 06/11] Phonet: common socket glue Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 08/11] Phonet: provide MAC header operations Rémi Denis-Courmont
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

This provides the basic SOCK_DGRAM transport protocol for Phonet.

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/net/phonet/phonet.h |    6 ++
 net/phonet/Makefile         |    1 +
 net/phonet/af_phonet.c      |  106 +++++++++++++++++++++++
 net/phonet/datagram.c       |  197 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 310 insertions(+), 0 deletions(-)
 create mode 100644 net/phonet/datagram.c

diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index 2ae5cbb..d3957d3 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -51,6 +51,9 @@ void pn_sock_hash(struct sock *sk);
 void pn_sock_unhash(struct sock *sk);
 int pn_sock_get_port(struct sock *sk, unsigned short sport);
 
+int pn_skb_send(struct sock *sk, struct sk_buff *skb,
+		const struct sockaddr_pn *target);
+
 static inline struct phonethdr *pn_hdr(struct sk_buff *skb)
 {
 	return (struct phonethdr *)skb_network_header(skb);
@@ -95,4 +98,7 @@ int phonet_proto_register(int protocol, struct phonet_protocol *pp);
 void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
 
 void phonet_netlink_register(void);
+int isi_register(void);
+void isi_unregister(void);
+
 #endif
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
index c1d671d..d218abc 100644
--- a/net/phonet/Makefile
+++ b/net/phonet/Makefile
@@ -4,4 +4,5 @@ phonet-objs := \
 	pn_dev.o \
 	pn_netlink.o \
 	socket.o \
+	datagram.o \
 	af_phonet.o
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index ba54d53..e6771d3 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -99,6 +99,101 @@ static struct net_proto_family phonet_proto_family = {
 	.owner = THIS_MODULE,
 };
 
+/*
+ * Prepends an ISI header and sends a datagram.
+ */
+static int pn_send(struct sk_buff *skb, struct net_device *dev,
+			u16 dst, u16 src, u8 res)
+{
+	struct phonethdr *ph;
+	int err;
+
+	if (skb->len + 2 > 0xffff) {
+		/* Phonet length field would overflow */
+		err = -EMSGSIZE;
+		goto drop;
+	}
+
+	skb_reset_transport_header(skb);
+	WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
+	skb_push(skb, sizeof(struct phonethdr));
+	skb_reset_network_header(skb);
+	ph = pn_hdr(skb);
+	ph->pn_rdev = pn_dev(dst);
+	ph->pn_sdev = pn_dev(src);
+	ph->pn_res = res;
+	ph->pn_length = __cpu_to_be16(skb->len + 2 - sizeof(*ph));
+	ph->pn_robj = pn_obj(dst);
+	ph->pn_sobj = pn_obj(src);
+
+	skb->protocol = htons(ETH_P_PHONET);
+	skb->priority = 0;
+	skb->dev = dev;
+
+	if (pn_addr(src) == pn_addr(dst)) {
+		skb_reset_mac_header(skb);
+		skb->pkt_type = PACKET_LOOPBACK;
+		skb_orphan(skb);
+		netif_rx_ni(skb);
+		err = 0;
+	} else {
+		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+					NULL, NULL, skb->len);
+		if (err < 0) {
+			err = -EHOSTUNREACH;
+			goto drop;
+		}
+		err = dev_queue_xmit(skb);
+	}
+
+	return err;
+drop:
+	kfree_skb(skb);
+	return err;
+}
+
+/*
+ * Create a Phonet header for the skb and send it out. Returns
+ * non-zero error code if failed. The skb is freed then.
+ */
+int pn_skb_send(struct sock *sk, struct sk_buff *skb,
+		const struct sockaddr_pn *target)
+{
+	struct net_device *dev;
+	struct pn_sock *pn = pn_sk(sk);
+	int err;
+	u16 src;
+	u8 daddr = pn_sockaddr_get_addr(target), saddr = PN_NO_ADDR;
+
+	err = -EHOSTUNREACH;
+	if (sk->sk_bound_dev_if)
+		dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
+	else
+		dev = phonet_device_get(sock_net(sk));
+	if (!dev || !(dev->flags & IFF_UP))
+		goto drop;
+
+	saddr = phonet_address_get(dev, daddr);
+	if (saddr == PN_NO_ADDR)
+		goto drop;
+
+	src = pn->sobject;
+	if (!pn_addr(src))
+		src = pn_object(saddr, pn_obj(src));
+
+	err = pn_send(skb, dev, pn_sockaddr_get_object(target),
+			src, pn_sockaddr_get_resource(target));
+	dev_put(dev);
+	return err;
+
+drop:
+	kfree_skb(skb);
+	if (dev)
+		dev_put(dev);
+	return err;
+}
+EXPORT_SYMBOL(pn_skb_send);
+
 /* packet type functions */
 
 /*
@@ -226,11 +321,22 @@ static int __init phonet_init(void)
 	phonet_device_init();
 	dev_add_pack(&phonet_packet_type);
 	phonet_netlink_register();
+
+	err = isi_register();
+	if (err)
+		goto err;
 	return 0;
+
+err:
+	sock_unregister(AF_PHONET);
+	dev_remove_pack(&phonet_packet_type);
+	phonet_device_exit();
+	return err;
 }
 
 static void __exit phonet_exit(void)
 {
+	isi_unregister();
 	sock_unregister(AF_PHONET);
 	dev_remove_pack(&phonet_packet_type);
 	phonet_device_exit();
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
new file mode 100644
index 0000000..e087862
--- /dev/null
+++ b/net/phonet/datagram.c
@@ -0,0 +1,197 @@
+/*
+ * File: datagram.c
+ *
+ * Datagram (ISI) Phonet sockets
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+ * Original author: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/socket.h>
+#include <asm/ioctls.h>
+#include <net/sock.h>
+
+#include <linux/phonet.h>
+#include <net/phonet/phonet.h>
+
+static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+
+/* associated socket ceases to exist */
+static void pn_sock_close(struct sock *sk, long timeout)
+{
+	sk_common_release(sk);
+}
+
+static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+	struct sk_buff *skb;
+	int answ;
+
+	switch (cmd) {
+	case SIOCINQ:
+		lock_sock(sk);
+		skb = skb_peek(&sk->sk_receive_queue);
+		answ = skb ? skb->len : 0;
+		release_sock(sk);
+		return put_user(answ, (int __user *)arg);
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+/* Destroy socket. All references are gone. */
+static void pn_destruct(struct sock *sk)
+{
+	skb_queue_purge(&sk->sk_receive_queue);
+}
+
+static int pn_init(struct sock *sk)
+{
+	sk->sk_destruct = pn_destruct;
+	return 0;
+}
+
+static int pn_sendmsg(struct kiocb *iocb, struct sock *sk,
+			struct msghdr *msg, size_t len)
+{
+	struct sockaddr_pn *target;
+	struct sk_buff *skb;
+	int err;
+
+	if (msg->msg_flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	if (msg->msg_name == NULL)
+		return -EDESTADDRREQ;
+
+	if (msg->msg_namelen < sizeof(struct sockaddr_pn))
+		return -EINVAL;
+
+	target = (struct sockaddr_pn *)msg->msg_name;
+	if (target->spn_family != AF_PHONET)
+		return -EAFNOSUPPORT;
+
+	skb = sock_alloc_send_skb(sk, MAX_PHONET_HEADER + len,
+					msg->msg_flags & MSG_DONTWAIT, &err);
+	if (skb == NULL)
+		return err;
+	skb_reserve(skb, MAX_PHONET_HEADER);
+
+	err = memcpy_fromiovec((void *)skb_put(skb, len), msg->msg_iov, len);
+	if (err < 0) {
+		kfree_skb(skb);
+		return err;
+	}
+
+	/*
+	 * Fill in the Phonet header and
+	 * finally pass the packet forwards.
+	 */
+	err = pn_skb_send(sk, skb, target);
+
+	/* If ok, return len. */
+	return (err >= 0) ? len : err;
+}
+
+static int pn_recvmsg(struct kiocb *iocb, struct sock *sk,
+			struct msghdr *msg, size_t len, int noblock,
+			int flags, int *addr_len)
+{
+	struct sk_buff *skb = NULL;
+	struct sockaddr_pn sa;
+	int rval = -EOPNOTSUPP;
+	int copylen;
+
+	if (flags & MSG_OOB)
+		goto out_nofree;
+
+	if (addr_len)
+		*addr_len = sizeof(sa);
+
+	skb = skb_recv_datagram(sk, flags, noblock, &rval);
+	if (skb == NULL)
+		goto out_nofree;
+
+	pn_skb_get_src_sockaddr(skb, &sa);
+
+	copylen = skb->len;
+	if (len < copylen) {
+		msg->msg_flags |= MSG_TRUNC;
+		copylen = len;
+	}
+
+	rval = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copylen);
+	if (rval) {
+		rval = -EFAULT;
+		goto out;
+	}
+
+	rval = (flags & MSG_TRUNC) ? skb->len : copylen;
+
+	if (msg->msg_name != NULL)
+		memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn));
+
+out:
+	skb_free_datagram(sk, skb);
+
+out_nofree:
+	return rval;
+}
+
+/* Queue an skb for a sock. */
+static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	int err = sock_queue_rcv_skb(sk, skb);
+	if (err < 0)
+		kfree_skb(skb);
+	return err ? NET_RX_DROP : NET_RX_SUCCESS;
+}
+
+/* Module registration */
+static struct proto pn_proto = {
+	.close		= pn_sock_close,
+	.ioctl		= pn_ioctl,
+	.init		= pn_init,
+	.sendmsg	= pn_sendmsg,
+	.recvmsg	= pn_recvmsg,
+	.backlog_rcv	= pn_backlog_rcv,
+	.hash		= pn_sock_hash,
+	.unhash		= pn_sock_unhash,
+	.get_port	= pn_sock_get_port,
+	.obj_size	= sizeof(struct pn_sock),
+	.owner		= THIS_MODULE,
+	.name		= "PHONET",
+};
+
+static struct phonet_protocol pn_dgram_proto = {
+	.ops		= &phonet_dgram_ops,
+	.prot		= &pn_proto,
+	.sock_type	= SOCK_DGRAM,
+};
+
+int __init isi_register(void)
+{
+	return phonet_proto_register(PN_PROTO_PHONET, &pn_dgram_proto);
+}
+
+void __exit isi_unregister(void)
+{
+	phonet_proto_unregister(PN_PROTO_PHONET, &pn_dgram_proto);
+}
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/11] Phonet: provide MAC header operations
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (6 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 07/11] Phonet: Phonet datagram transport protocol Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 09/11] Phonet: proc interface for port range Rémi Denis-Courmont
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/linux/if_phonet.h |    4 ++++
 net/phonet/af_phonet.c    |   29 +++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/include/linux/if_phonet.h b/include/linux/if_phonet.h
index 22df25f..7e98921 100644
--- a/include/linux/if_phonet.h
+++ b/include/linux/if_phonet.h
@@ -12,3 +12,7 @@
 /* 6 bytes header + 65535 bytes payload */
 #define PHONET_MAX_MTU		65541
 #define PHONET_DEV_MTU		PHONET_MAX_MTU
+
+#ifdef __KERNEL__
+extern struct header_ops phonet_header_ops;
+#endif
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index e6771d3..51397ff 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -99,6 +99,35 @@ static struct net_proto_family phonet_proto_family = {
 	.owner = THIS_MODULE,
 };
 
+/* Phonet device header operations */
+static int pn_header_create(struct sk_buff *skb, struct net_device *dev,
+				unsigned short type, const void *daddr,
+				const void *saddr, unsigned len)
+{
+	u8 *media = skb_push(skb, 1);
+
+	if (type != ETH_P_PHONET)
+		return -1;
+
+	if (!saddr)
+		saddr = dev->dev_addr;
+	*media = *(const u8 *)saddr;
+	return 1;
+}
+
+static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+{
+	const u8 *media = skb_mac_header(skb);
+	*haddr = *media;
+	return 1;
+}
+
+struct header_ops phonet_header_ops = {
+	.create = pn_header_create,
+	.parse = pn_header_parse,
+};
+EXPORT_SYMBOL(phonet_header_ops);
+
 /*
  * Prepends an ISI header and sends a datagram.
  */
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/11] Phonet: proc interface for port range
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (7 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 08/11] Phonet: provide MAC header operations Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 10/11] Phonet: emit errors when a packet cannot be delivered locally Rémi Denis-Courmont
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

Phonet endpoints are bound to individual ports.
This provides a /proc/sys/net/phonet (or sysctl) interface for
selecting the range of automatically allocated ports (much like the
ip_local_port_range with IPv4).

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/net/phonet/phonet.h |    3 +
 net/phonet/Makefile         |    1 +
 net/phonet/af_phonet.c      |    3 +
 net/phonet/socket.c         |    3 +-
 net/phonet/sysctl.c         |  113 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 122 insertions(+), 1 deletions(-)
 create mode 100644 net/phonet/sysctl.c

diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index d3957d3..1c6f7e7 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -47,6 +47,7 @@ static inline struct pn_sock *pn_sk(struct sock *sk)
 extern const struct proto_ops phonet_dgram_ops;
 
 struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa);
+void phonet_get_local_port_range(int *min, int *max);
 void pn_sock_hash(struct sock *sk);
 void pn_sock_unhash(struct sock *sk);
 int pn_sock_get_port(struct sock *sk, unsigned short sport);
@@ -97,6 +98,8 @@ struct phonet_protocol {
 int phonet_proto_register(int protocol, struct phonet_protocol *pp);
 void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
 
+int phonet_sysctl_init(void);
+void phonet_sysctl_exit(void);
 void phonet_netlink_register(void);
 int isi_register(void);
 void isi_unregister(void);
diff --git a/net/phonet/Makefile b/net/phonet/Makefile
index d218abc..ae9c3ed 100644
--- a/net/phonet/Makefile
+++ b/net/phonet/Makefile
@@ -5,4 +5,5 @@ phonet-objs := \
 	pn_netlink.o \
 	socket.o \
 	datagram.o \
+	sysctl.o \
 	af_phonet.o
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 51397ff..50dc258 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -350,6 +350,7 @@ static int __init phonet_init(void)
 	phonet_device_init();
 	dev_add_pack(&phonet_packet_type);
 	phonet_netlink_register();
+	phonet_sysctl_init();
 
 	err = isi_register();
 	if (err)
@@ -357,6 +358,7 @@ static int __init phonet_init(void)
 	return 0;
 
 err:
+	phonet_sysctl_exit();
 	sock_unregister(AF_PHONET);
 	dev_remove_pack(&phonet_packet_type);
 	phonet_device_exit();
@@ -366,6 +368,7 @@ err:
 static void __exit phonet_exit(void)
 {
 	isi_unregister();
+	phonet_sysctl_exit();
 	sock_unregister(AF_PHONET);
 	dev_remove_pack(&phonet_packet_type);
 	phonet_device_exit();
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 99a4945..dfd4061 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -273,8 +273,9 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
 
 	if (!sport) {
 		/* search free port */
-		int port, pmin = 0x40, pmax = 0x7f;
+		int port, pmin, pmax;
 
+		phonet_get_local_port_range(&pmin, &pmax);
 		for (port = pmin; port <= pmax; port++) {
 			port_cur++;
 			if (port_cur < pmin || port_cur > pmax)
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c
new file mode 100644
index 0000000..600a430
--- /dev/null
+++ b/net/phonet/sysctl.c
@@ -0,0 +1,113 @@
+/*
+ * File: sysctl.c
+ *
+ * Phonet /proc/sys/net/phonet interface implementation
+ *
+ * Copyright (C) 2008 Nokia Corporation.
+ *
+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/seqlock.h>
+#include <linux/sysctl.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#define DYNAMIC_PORT_MIN	0x40
+#define DYNAMIC_PORT_MAX	0x7f
+
+static DEFINE_SEQLOCK(local_port_range_lock);
+static int local_port_range_min[2] = {0, 0};
+static int local_port_range_max[2] = {1023, 1023};
+static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX};
+static struct ctl_table_header *phonet_table_hrd;
+
+static void set_local_port_range(int range[2])
+{
+	write_seqlock(&local_port_range_lock);
+	local_port_range[0] = range[0];
+	local_port_range[1] = range[1];
+	write_sequnlock(&local_port_range_lock);
+}
+
+void phonet_get_local_port_range(int *min, int *max)
+{
+	unsigned seq;
+	do {
+		seq = read_seqbegin(&local_port_range_lock);
+		if (min)
+			*min = local_port_range[0];
+		if (max)
+			*max = local_port_range[1];
+	} while (read_seqretry(&local_port_range_lock, seq));
+}
+
+static int proc_local_port_range(ctl_table *table, int write, struct file *filp,
+				void __user *buffer,
+				size_t *lenp, loff_t *ppos)
+{
+	int ret;
+	int range[2] = {local_port_range[0], local_port_range[1]};
+	ctl_table tmp = {
+		.data = &range,
+		.maxlen = sizeof(range),
+		.mode = table->mode,
+		.extra1 = &local_port_range_min,
+		.extra2 = &local_port_range_max,
+	};
+
+	ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos);
+
+	if (write && ret == 0) {
+		if (range[1] < range[0])
+			ret = -EINVAL;
+		else
+			set_local_port_range(range);
+	}
+
+	return ret;
+}
+
+static struct ctl_table phonet_table[] = {
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "local_port_range",
+		.data		= &local_port_range,
+		.maxlen		= sizeof(local_port_range),
+		.mode		= 0644,
+		.proc_handler	= &proc_local_port_range,
+		.strategy	= NULL,
+	},
+	{ .ctl_name = 0 }
+};
+
+struct ctl_path phonet_ctl_path[] = {
+	{ .procname = "net", .ctl_name = CTL_NET, },
+	{ .procname = "phonet", .ctl_name = CTL_UNNUMBERED, },
+	{ },
+};
+
+int __init phonet_sysctl_init(void)
+{
+	phonet_table_hrd = register_sysctl_paths(phonet_ctl_path, phonet_table);
+	return phonet_table_hrd == NULL ? -ENOMEM : 0;
+}
+
+void phonet_sysctl_exit(void)
+{
+	unregister_sysctl_table(phonet_table_hrd);
+}
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/11] Phonet: emit errors when a packet cannot be delivered locally
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (8 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 09/11] Phonet: proc interface for port range Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-22 15:47 ` [PATCH 11/11] Phonet: kernel documentation Rémi Denis-Courmont
  2008-09-23  3:16 ` [PATCH 00/11] PhoNet protocols stack v2 David Miller
  11 siblings, 0 replies; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

When there is no listener socket for a received packet, send an error
back to the sender.

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/linux/phonet.h      |   32 ++++++++++++++
 include/net/phonet/phonet.h |    5 ++
 net/phonet/af_phonet.c      |   96 +++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 129 insertions(+), 4 deletions(-)

diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index 001c0e6..3a027f5 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -45,6 +45,38 @@ struct phonethdr {
 	__u8	pn_sobj;
 } __attribute__((packed));
 
+/* Common Phonet payload header */
+struct phonetmsg {
+	__u8	pn_trans_id;	/* transaction ID */
+	__u8	pn_msg_id;	/* message type */
+	union {
+		struct {
+			__u8	pn_submsg_id;	/* message subtype */
+			__u8	pn_data[5];
+		} base;
+		struct {
+			__u16	pn_e_res_id;	/* extended resource ID */
+			__u8	pn_e_submsg_id;	/* message subtype */
+			__u8	pn_e_data[3];
+		} ext;
+	} pn_msg_u;
+};
+#define PN_COMMON_MESSAGE	0xF0
+#define PN_PREFIX		0xE0 /* resource for extended messages */
+#define pn_submsg_id		pn_msg_u.base.pn_submsg_id
+#define pn_e_submsg_id		pn_msg_u.ext.pn_e_submsg_id
+#define pn_e_res_id		pn_msg_u.ext.pn_e_res_id
+#define pn_data			pn_msg_u.base.pn_data
+#define pn_e_data		pn_msg_u.ext.pn_e_data
+
+/* data for unreachable errors */
+#define PN_COMM_SERVICE_NOT_IDENTIFIED_RESP	0x01
+#define PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP	0x14
+#define pn_orig_msg_id		pn_data[0]
+#define pn_status		pn_data[1]
+#define pn_e_orig_msg_id	pn_e_data[0]
+#define pn_e_status		pn_e_data[1]
+
 /* Phonet socket address structure */
 struct sockaddr_pn {
 	sa_family_t spn_family;
diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index 1c6f7e7..d4e7250 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -60,6 +60,11 @@ static inline struct phonethdr *pn_hdr(struct sk_buff *skb)
 	return (struct phonethdr *)skb_network_header(skb);
 }
 
+static inline struct phonetmsg *pn_msg(struct sk_buff *skb)
+{
+	return (struct phonetmsg *)skb_transport_header(skb);
+}
+
 /*
  * Get the other party's sockaddr from received skb. The skb begins
  * with a Phonet header.
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 50dc258..1d8df6b 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -132,7 +132,7 @@ EXPORT_SYMBOL(phonet_header_ops);
  * Prepends an ISI header and sends a datagram.
  */
 static int pn_send(struct sk_buff *skb, struct net_device *dev,
-			u16 dst, u16 src, u8 res)
+			u16 dst, u16 src, u8 res, u8 irq)
 {
 	struct phonethdr *ph;
 	int err;
@@ -163,7 +163,10 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
 		skb_reset_mac_header(skb);
 		skb->pkt_type = PACKET_LOOPBACK;
 		skb_orphan(skb);
-		netif_rx_ni(skb);
+		if (irq)
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
 		err = 0;
 	} else {
 		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
@@ -181,6 +184,19 @@ drop:
 	return err;
 }
 
+static int pn_raw_send(const void *data, int len, struct net_device *dev,
+			u16 dst, u16 src, u8 res)
+{
+	struct sk_buff *skb = alloc_skb(MAX_PHONET_HEADER + len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	skb_reserve(skb, MAX_PHONET_HEADER);
+	__skb_put(skb, len);
+	skb_copy_to_linear_data(skb, data, len);
+	return pn_send(skb, dev, dst, src, res, 1);
+}
+
 /*
  * Create a Phonet header for the skb and send it out. Returns
  * non-zero error code if failed. The skb is freed then.
@@ -211,7 +227,7 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb,
 		src = pn_object(saddr, pn_obj(src));
 
 	err = pn_send(skb, dev, pn_sockaddr_get_object(target),
-			src, pn_sockaddr_get_resource(target));
+			src, pn_sockaddr_get_resource(target), 0);
 	dev_put(dev);
 	return err;
 
@@ -223,6 +239,73 @@ drop:
 }
 EXPORT_SYMBOL(pn_skb_send);
 
+/* Do not send an error message in response to an error message */
+static inline int can_respond(struct sk_buff *skb)
+{
+	const struct phonethdr *ph;
+	const struct phonetmsg *pm;
+	u8 submsg_id;
+
+	if (!pskb_may_pull(skb, 3))
+		return 0;
+
+	ph = pn_hdr(skb);
+	if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev)
+		return 0; /* we are not the destination */
+	if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5))
+		return 0;
+
+	ph = pn_hdr(skb); /* re-acquires the pointer */
+	pm = pn_msg(skb);
+	if (pm->pn_msg_id != PN_COMMON_MESSAGE)
+		return 1;
+	submsg_id = (ph->pn_res == PN_PREFIX)
+		? pm->pn_e_submsg_id : pm->pn_submsg_id;
+	if (submsg_id != PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP &&
+		pm->pn_e_submsg_id != PN_COMM_SERVICE_NOT_IDENTIFIED_RESP)
+		return 1;
+	return 0;
+}
+
+static int send_obj_unreachable(struct sk_buff *rskb)
+{
+	const struct phonethdr *oph = pn_hdr(rskb);
+	const struct phonetmsg *opm = pn_msg(rskb);
+	struct phonetmsg resp;
+
+	memset(&resp, 0, sizeof(resp));
+	resp.pn_trans_id = opm->pn_trans_id;
+	resp.pn_msg_id = PN_COMMON_MESSAGE;
+	if (oph->pn_res == PN_PREFIX) {
+		resp.pn_e_res_id = opm->pn_e_res_id;
+		resp.pn_e_submsg_id = PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP;
+		resp.pn_e_orig_msg_id = opm->pn_msg_id;
+		resp.pn_e_status = 0;
+	} else {
+		resp.pn_submsg_id = PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP;
+		resp.pn_orig_msg_id = opm->pn_msg_id;
+		resp.pn_status = 0;
+	}
+	return pn_raw_send(&resp, sizeof(resp), rskb->dev,
+				pn_object(oph->pn_sdev, oph->pn_sobj),
+				pn_object(oph->pn_rdev, oph->pn_robj),
+				oph->pn_res);
+}
+
+static int send_reset_indications(struct sk_buff *rskb)
+{
+	struct phonethdr *oph = pn_hdr(rskb);
+	static const u8 data[4] = {
+		0x00 /* trans ID */, 0x10 /* subscribe msg */,
+		0x00 /* subscription count */, 0x00 /* dummy */
+	};
+
+	return pn_raw_send(data, sizeof(data), rskb->dev,
+				pn_object(oph->pn_sdev, 0x00),
+				pn_object(oph->pn_rdev, oph->pn_robj), 0x10);
+}
+
+
 /* packet type functions */
 
 /*
@@ -260,8 +343,13 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
 		goto out; /* currently, we cannot be device 0 */
 
 	sk = pn_find_sock_by_sa(&sa);
-	if (sk == NULL)
+	if (sk == NULL) {
+		if (can_respond(skb)) {
+			send_obj_unreachable(skb);
+			send_reset_indications(skb);
+		}
 		goto out;
+	}
 
 	/* Push data to the socket (or other sockets connected to it). */
 	return sk_receive_skb(sk, skb, 0);
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 11/11] Phonet: kernel documentation
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (9 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 10/11] Phonet: emit errors when a packet cannot be delivered locally Rémi Denis-Courmont
@ 2008-09-22 15:47 ` Rémi Denis-Courmont
  2008-09-23 21:43   ` Randy Dunlap
  2008-09-23  3:16 ` [PATCH 00/11] PhoNet protocols stack v2 David Miller
  11 siblings, 1 reply; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-22 15:47 UTC (permalink / raw)
  To: netdev

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 Documentation/networking/phonet.txt |  111 +++++++++++++++++++++++++++++++++++
 1 files changed, 111 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/networking/phonet.txt

diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
new file mode 100644
index 0000000..f3c72e0
--- /dev/null
+++ b/Documentation/networking/phonet.txt
@@ -0,0 +1,111 @@
+Linux Phonet protocol family
+============================
+
+Introduction
+------------
+
+Phonet is a packet protocol used by Nokia cellular modems for both IPC
+and RPC. With the Linux Phonet socket family, Linux host processes can
+receive and send messages from/to the modem, or any other external
+device attached to the modem. The modem takes care of routing.
+
+Phonet packets can be exchanged through various hardware connections
+depending on the device, such as:
+  - USB with the CDC Phonet interface,
+  - infrared,
+  - Bluetooth,
+  - an RS232 serial port (with a dedicated "FBUS" line discipline),
+  - the SSI bus with some TI OMAP processors.
+
+
+Packets format
+--------------
+
+Phonet packet have a common header as follow:
+
+  struct phonethdr {
+    uint8_t  pn_media;  /* Media type (link-layer identifier) */
+    uint8_t  pn_rdev;   /* Receiver device ID */
+    uint8_t  pn_sdev;   /* Sender device ID */
+    uint8_t  pn_res;    /* Resource ID or function */
+    uint16_t pn_length; /* Big-endian message byte length (minus 6) */
+    uint8_t  pn_robj;   /* Receiver object ID */
+    uint8_t  pn_sobj;   /* Sender object ID */
+  };
+
+The device ID is split: the 6 higher order bits consitutes the device
+address, while the 2 lower order bits are used for multiplexing, as are
+the 8-bits object identifiers. As such, Phonet can be considered as a
+network layer with 6 bits of address space and 10 bits for transport
+protocol (much like port numbers in IP world).
+
+The modem always has address number zero. Each other device has a its
+own 6-bits address.
+
+
+Link layer
+----------
+
+Phonet links are always point-to-point links. The link layer header
+consists of a single Phonet media type byte. It uniquely identifies the
+link through which the packet is transmitted, from the modem's
+perspective.
+
+Linux Phonet network interfaces use a dedicated link layer type
+(ETH_P_PHONET) which is out of the Ethernet type range. They can only
+send and receive Phonet packets.
+
+Note that Phonet interfaces are not allowed to re-order packets, so
+only the (default) Linux FIFO qdisc should be used with them.
+
+
+Network layer
+-------------
+
+The Phonet socket address family maps the Phonet packet header:
+
+  struct sockaddr_pn {
+    sa_family_t spn_family;    /* AF_PHONET */
+    uint8_t     spn_obj;       /* Object ID */
+    uint8_t     spn_dev;       /* Device ID */
+    uint8_t     spn_resource;  /* Resource or function */
+    uint8_t     spn_zero[...]; /* Padding */
+  };
+
+The resource field is only used when sending and receiving;
+It is ignored by bind() and getsockname().
+
+
+Low-level datagram protocol
+---------------------------
+
+Applications can send Phonet messages using the Phonet datagram socket
+protocol from the PF_PHONET family. Each socket is bound to one of the
+2^10 object IDs available, and can send and receive packets with any
+other peer.
+
+  struct sockaddr_pn addr = { .spn_family = AF_PHONET, };
+  ssize_t len;
+  socklen_t addrlen = sizeof(addr);
+  int fd;
+
+  fd = socket(PF_PHONET, SOCK_DGRAM, 0);
+  bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+  /* ... */
+
+  sendto(fd, msg, msglen, 0, (struct sockaddr *)&addr, sizeof(addr));
+  len = recvfrom(fd, buf, sizeof(buf), 0,
+                 (struct sockaddr *)&addr, &addrlen);
+
+This protocol follows the SOCK_DGRAM connection-less semantics.
+However, connect() and getpeername() are not supported, as they did
+not seem useful with Phonet usages (could be added easily).
+
+
+Authors
+-------
+
+Linux Phonet was initially written by Sakari Ailus.
+Other contributors include Mikä Liljeberg, Andras Domokos,
+Carlos Chinea and Rémi Denis-Courmont.
+Copyright (C) 2008 Nokia Corporation.
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 00/11] PhoNet protocols stack v2
  2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
                   ` (10 preceding siblings ...)
  2008-09-22 15:47 ` [PATCH 11/11] Phonet: kernel documentation Rémi Denis-Courmont
@ 2008-09-23  3:16 ` David Miller
  11 siblings, 0 replies; 19+ messages in thread
From: David Miller @ 2008-09-23  3:16 UTC (permalink / raw)
  To: remi.denis-courmont; +Cc: netdev

From: "Rémi Denis-Courmont" <remi.denis-courmont@nokia.com>
Date: Mon, 22 Sep 2008 18:45:54 +0300

>         Hello,
> 
> This patch series is the second attempt at support for PhoNet network protocol 
> stack in the Linux kernel and trying to address various comments already 
> received on the mailing list. This protocol is the primary interface to Nokia 
> cellular modem engines. We are integrating it to the Linux kernel in order to 
> support HSPA cellular data connectivity on the Maemo Software platform.
> 
> This patchset provides a "raw" datagram protocol as a starting point, and is 
> based on the current net-next-2.6.
> 
> Any comments welcome.

This seems good enough to initially merge, so I applied all of these
patches to net-next-2.6

Please send any bug fixes or updates relative to this, thanks!

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/11] Phonet: Netlink interface
  2008-09-22 15:47 ` [PATCH 05/11] Phonet: Netlink interface Rémi Denis-Courmont
@ 2008-09-23 12:10   ` Thomas Graf
  2008-09-24 11:30     ` Rémi Denis-Courmont
  0 siblings, 1 reply; 19+ messages in thread
From: Thomas Graf @ 2008-09-23 12:10 UTC (permalink / raw)
  To: Rémi Denis-Courmont; +Cc: netdev

Hello!

* R?mi Denis-Courmont <remi.denis-courmont@nokia.com> 2008-09-22 18:47
> +static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
> +{
> +	struct rtattr **rta = attr;
> +	struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
> +	struct net_device *dev;
> +	int err;
> +	u8 pnaddr;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +
> +	ASSERT_RTNL();
> +
> +	if (rta[IFA_LOCAL - 1] == NULL)
> +		return -EINVAL;

Please do not use the old attribute buffer anymore. It's use is racy
ever since we started dropping the rtnl semaphore in order to load
modules. It would be safe in this particular case but it shouldn't be
used for new code.

Take a look at rtnl_setlink() for an example on how to use the interface
correctly.

> +	memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);

This is not safe, the attribute payload needs to be verified before its
use.

Please use the new netlink interface, all functions named RTA_ or rattr_
are deprecated. The new interface provides a trivial method to validate
attributes while they are being parsed.

> +static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
> +			u32 pid, u32 seq, int event)
> +{
> +	struct ifaddrmsg *ifm;
> +	struct nlmsghdr *nlh;
> +	unsigned int orig_len = skb->len;
> +
> +	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg));
> +	ifm = NLMSG_DATA(nlh);

Please use nlmsg_put() and nlmsg_data()

> +	ifm->ifa_family = AF_PHONET;
> +	ifm->ifa_prefixlen = 0;
> +	ifm->ifa_flags = IFA_F_PERMANENT;
> +	ifm->ifa_scope = RT_SCOPE_HOST;
> +	ifm->ifa_index = dev->ifindex;
> +	RTA_PUT(skb, IFA_LOCAL, 1, &addr);
> +	nlh->nlmsg_len = skb->len - orig_len;

See rtnl_fill_ifinfo() for an example.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 11/11] Phonet: kernel documentation
  2008-09-22 15:47 ` [PATCH 11/11] Phonet: kernel documentation Rémi Denis-Courmont
@ 2008-09-23 21:43   ` Randy Dunlap
  2008-09-24 12:15     ` [PATCH] Phonet: improve documentation Rémi Denis-Courmont
  0 siblings, 1 reply; 19+ messages in thread
From: Randy Dunlap @ 2008-09-23 21:43 UTC (permalink / raw)
  To: Rémi Denis-Courmont; +Cc: netdev

On Mon, 22 Sep 2008 18:47:25 +0300 Rémi Denis-Courmont wrote:

> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
> ---
>  Documentation/networking/phonet.txt |  111 +++++++++++++++++++++++++++++++++++
>  1 files changed, 111 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/networking/phonet.txt
> 
> diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
> new file mode 100644
> index 0000000..f3c72e0
> --- /dev/null
> +++ b/Documentation/networking/phonet.txt
> @@ -0,0 +1,111 @@
> +Linux Phonet protocol family
> +============================
> +
> +Introduction
> +------------
> +
> +Phonet is a packet protocol used by Nokia cellular modems for both IPC
> +and RPC. With the Linux Phonet socket family, Linux host processes can
> +receive and send messages from/to the modem, or any other external
> +device attached to the modem. The modem takes care of routing.
> +
> +Phonet packets can be exchanged through various hardware connections
> +depending on the device, such as:
> +  - USB with the CDC Phonet interface,
> +  - infrared,
> +  - Bluetooth,
> +  - an RS232 serial port (with a dedicated "FBUS" line discipline),
> +  - the SSI bus with some TI OMAP processors.
> +
> +
> +Packets format
> +--------------
> +
> +Phonet packet have a common header as follow:

          packets

> +
> +  struct phonethdr {
> +    uint8_t  pn_media;  /* Media type (link-layer identifier) */
> +    uint8_t  pn_rdev;   /* Receiver device ID */
> +    uint8_t  pn_sdev;   /* Sender device ID */
> +    uint8_t  pn_res;    /* Resource ID or function */
> +    uint16_t pn_length; /* Big-endian message byte length (minus 6) */
> +    uint8_t  pn_robj;   /* Receiver object ID */
> +    uint8_t  pn_sobj;   /* Sender object ID */
> +  };
> +
> +The device ID is split: the 6 higher order bits consitutes the device

                                 higher-order bits constitute

> +address, while the 2 lower order bits are used for multiplexing, as are

                        lower-order

> +the 8-bits object identifiers. As such, Phonet can be considered as a

       8-bit

> +network layer with 6 bits of address space and 10 bits for transport
> +protocol (much like port numbers in IP world).
> +
> +The modem always has address number zero. Each other device has a its

                                             All other devices have their
> +own 6-bits address.

   own 6-bit address.


---
~Randy

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/11] Phonet: Netlink interface
  2008-09-23 12:10   ` Thomas Graf
@ 2008-09-24 11:30     ` Rémi Denis-Courmont
  2008-09-24 13:23       ` Thomas Graf
  0 siblings, 1 reply; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-24 11:30 UTC (permalink / raw)
  To: ext Thomas Graf; +Cc: netdev


	Hello,

On Tuesday 23 September 2008 15:10:02, you wrote:
> Please do not use the old attribute buffer anymore. It's use is racy
> ever since we started dropping the rtnl semaphore in order to load
> modules. It would be safe in this particular case but it shouldn't be
> used for new code.
>
> Take a look at rtnl_setlink() for an example on how to use the interface
> correctly. (...)

Ok, thanks. Would this work?

diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index b1ea19a..136622b 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -54,11 +54,17 @@ errout:
 		rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err);
 }
 
-static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
+static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = {
+	[IFA_LOCAL] = { .type = NLA_U8 },
+};
+
+static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr,
+			int op)
 {
-	struct rtattr **rta = attr;
-	struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
+	struct net *net = sock_net(skb->sk);
+	struct nlattr *tb[IFA_MAX+1];
 	struct net_device *dev;
+	struct ifaddrmsg *ifm;
 	int err;
 	u8 pnaddr;
 
@@ -67,53 +73,39 @@ static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
 
 	ASSERT_RTNL();
 
-	if (rta[IFA_LOCAL - 1] == NULL)
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_phonet_policy);
+	if (err < 0)
+		return err;
+
+	ifm = nlmsg_data(nlh);
+	if (tb[IFA_LOCAL] == NULL)
+		return -EINVAL;
+	pnaddr = nla_get_u8(tb[IFA_LOCAL]);
+	if (pnaddr & 3)
+		/* Phonet addresses only have 6 high-order bits */
 		return -EINVAL;
 
-	dev = __dev_get_by_index(&init_net, ifm->ifa_index);
+	dev = __dev_get_by_index(net, ifm->ifa_index);
 	if (dev == NULL)
 		return -ENODEV;
 
-	if (ifm->ifa_prefixlen > 0)
-		return -EINVAL;
-
-	memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);
-
-	err = phonet_address_add(dev, pnaddr);
+	if (op == RTM_NEWADDR)
+		err = phonet_address_add(dev, pnaddr);
+	else
+		err = phonet_address_del(dev, pnaddr);
 	if (!err)
-		rtmsg_notify(RTM_NEWADDR, dev, pnaddr);
+		rtmsg_notify(op, dev, pnaddr);
 	return err;
 }
 
-static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
+static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
 {
-	struct rtattr **rta = attr;
-	struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
-	struct net_device *dev;
-	int err;
-	u8 pnaddr;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	ASSERT_RTNL();
-
-	if (rta[IFA_LOCAL - 1] == NULL)
-		return -EINVAL;
-
-	dev = __dev_get_by_index(&init_net, ifm->ifa_index);
-	if (dev == NULL)
-		return -ENODEV;
-
-	if (ifm->ifa_prefixlen > 0)
-		return -EADDRNOTAVAIL;
-
-	memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);
+	return addr_doit(skb, nlm, attr, RTM_NEWADDR);
+}
 
-	err = phonet_address_del(dev, pnaddr);
-	if (!err)
-		rtmsg_notify(RTM_DELADDR, dev, pnaddr);
-	return err;
+static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
+{
+	return addr_doit(skb, nlm, attr, RTM_DELADDR);
 }
 
 static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
@@ -121,25 +113,23 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
 {
 	struct ifaddrmsg *ifm;
 	struct nlmsghdr *nlh;
-	unsigned int orig_len = skb->len;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg));
-	ifm = NLMSG_DATA(nlh);
+	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), 0);
+	if (nlh == NULL)
+		return -EMSGSIZE;
+
+	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_PHONET;
 	ifm->ifa_prefixlen = 0;
 	ifm->ifa_flags = IFA_F_PERMANENT;
-	ifm->ifa_scope = RT_SCOPE_HOST;
+	ifm->ifa_scope = RT_SCOPE_LINK;
 	ifm->ifa_index = dev->ifindex;
-	RTA_PUT(skb, IFA_LOCAL, 1, &addr);
-	nlh->nlmsg_len = skb->len - orig_len;
-
-	return 0;
-
-nlmsg_failure:
-rtattr_failure:
-	skb_trim(skb, orig_len);
+	NLA_PUT_U8(skb, IFA_LOCAL, addr);
+	return nlmsg_end(skb, nlh);
 
-	return -1;
+nla_put_failure:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
_

-- 
Rémi Denis-Courmont
Maemo Software, Nokia Devices R&D


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH] Phonet: improve documentation
  2008-09-23 21:43   ` Randy Dunlap
@ 2008-09-24 12:15     ` Rémi Denis-Courmont
  2008-09-24 15:45       ` Randy Dunlap
  0 siblings, 1 reply; 19+ messages in thread
From: Rémi Denis-Courmont @ 2008-09-24 12:15 UTC (permalink / raw)
  To: ext Randy Dunlap, David Miller; +Cc: netdev

Fix grammar errors spotted by Randy Dunlap,
and adds some more details.

Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 Documentation/networking/phonet.txt |   32 +++++++++++++++++++++-----------
 1 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
index f3c72e0..1506c31 100644
--- a/Documentation/networking/phonet.txt
+++ b/Documentation/networking/phonet.txt
@@ -21,7 +21,7 @@ depending on the device, such as:
 Packets format
 --------------
 
-Phonet packet have a common header as follow:
+Phonet packets have a common header as follow:
 
   struct phonethdr {
     uint8_t  pn_media;  /* Media type (link-layer identifier) */
@@ -33,14 +33,17 @@ Phonet packet have a common header as follow:
     uint8_t  pn_sobj;   /* Sender object ID */
   };
 
-The device ID is split: the 6 higher order bits consitutes the device
-address, while the 2 lower order bits are used for multiplexing, as are
-the 8-bits object identifiers. As such, Phonet can be considered as a
+On Linux, the link-layer header includes the pn_media byte (see below).
+The next 7 bytes are part of the network-layer header.
+
+The device ID is split: the 6 higher order-bits consitute the device
+address, while the 2 lower-order bits are used for multiplexing, as are
+the 8-bit object identifiers. As such, Phonet can be considered as a
 network layer with 6 bits of address space and 10 bits for transport
 protocol (much like port numbers in IP world).
 
-The modem always has address number zero. Each other device has a its
-own 6-bits address.
+The modem always has address number zero. All other device have a their
+own 6-bit address.
 
 
 Link layer
@@ -49,11 +52,18 @@ Link layer
 Phonet links are always point-to-point links. The link layer header
 consists of a single Phonet media type byte. It uniquely identifies the
 link through which the packet is transmitted, from the modem's
-perspective.
-
-Linux Phonet network interfaces use a dedicated link layer type
-(ETH_P_PHONET) which is out of the Ethernet type range. They can only
-send and receive Phonet packets.
+perspective. Each Phonet network device shall prepend and set the media
+type byte as appropriate. For convenience, a common phonet_header_ops
+link-layer header operations structure is provided. It sets the
+media type according to the network device hardware address.
+
+Linux Phonet network interfaces support a dedicated link layer packets
+type (ETH_P_PHONET) which is out of the Ethernet type range. They can
+only send and receive Phonet packets.
+
+The virtual TUN tunnel device driver can also be used for Phonet. This
+requires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case,
+there is no link-layer header, so there is no Phonet media type byte.
 
 Note that Phonet interfaces are not allowed to re-order packets, so
 only the (default) Linux FIFO qdisc should be used with them.
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 05/11] Phonet: Netlink interface
  2008-09-24 11:30     ` Rémi Denis-Courmont
@ 2008-09-24 13:23       ` Thomas Graf
  0 siblings, 0 replies; 19+ messages in thread
From: Thomas Graf @ 2008-09-24 13:23 UTC (permalink / raw)
  To: Rémi Denis-Courmont; +Cc: netdev

* R?mi Denis-Courmont <remi.denis-courmont@Nokia.com> 2008-09-24 14:30
> Ok, thanks. Would this work?

Yes, looks good.

> +	if (op == RTM_NEWADDR)
> +		err = phonet_address_add(dev, pnaddr);
> +	else
> +		err = phonet_address_del(dev, pnaddr);

You could do if (nlh->nlmsg_type == RTM_NEWADDR) here and register this
functions for both add and delete.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] Phonet: improve documentation
  2008-09-24 12:15     ` [PATCH] Phonet: improve documentation Rémi Denis-Courmont
@ 2008-09-24 15:45       ` Randy Dunlap
  0 siblings, 0 replies; 19+ messages in thread
From: Randy Dunlap @ 2008-09-24 15:45 UTC (permalink / raw)
  To: Rémi Denis-Courmont; +Cc: David Miller, netdev

Rémi Denis-Courmont wrote:
> Fix grammar errors spotted by Randy Dunlap,
> and adds some more details.

Um, let me try again, please.

> Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
> ---
>  Documentation/networking/phonet.txt |   32 +++++++++++++++++++++-----------
>  1 files changed, 21 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
> index f3c72e0..1506c31 100644
> --- a/Documentation/networking/phonet.txt
> +++ b/Documentation/networking/phonet.txt
> @@ -21,7 +21,7 @@ depending on the device, such as:
>  Packets format
>  --------------
>  
> -Phonet packet have a common header as follow:
> +Phonet packets have a common header as follow:

                                          follows:

>  
>    struct phonethdr {
>      uint8_t  pn_media;  /* Media type (link-layer identifier) */
> @@ -33,14 +33,17 @@ Phonet packet have a common header as follow:
>      uint8_t  pn_sobj;   /* Sender object ID */
>    };
>  
> -The device ID is split: the 6 higher order bits consitutes the device
> -address, while the 2 lower order bits are used for multiplexing, as are
> -the 8-bits object identifiers. As such, Phonet can be considered as a
> +On Linux, the link-layer header includes the pn_media byte (see below).
> +The next 7 bytes are part of the network-layer header.
> +
> +The device ID is split: the 6 higher order-bits consitute the device

                                 higher-order bits

> +address, while the 2 lower-order bits are used for multiplexing, as are
> +the 8-bit object identifiers. As such, Phonet can be considered as a
>  network layer with 6 bits of address space and 10 bits for transport
>  protocol (much like port numbers in IP world).
>  
> -The modem always has address number zero. Each other device has a its
> -own 6-bits address.
> +The modem always has address number zero. All other device have a their
> +own 6-bit address.
>  
>  
>  Link layer
> @@ -49,11 +52,18 @@ Link layer
>  Phonet links are always point-to-point links. The link layer header
>  consists of a single Phonet media type byte. It uniquely identifies the
>  link through which the packet is transmitted, from the modem's
> -perspective.
> -
> -Linux Phonet network interfaces use a dedicated link layer type
> -(ETH_P_PHONET) which is out of the Ethernet type range. They can only
> -send and receive Phonet packets.
> +perspective. Each Phonet network device shall prepend and set the media
> +type byte as appropriate. For convenience, a common phonet_header_ops
> +link-layer header operations structure is provided. It sets the
> +media type according to the network device hardware address.
> +
> +Linux Phonet network interfaces support a dedicated link layer packets
> +type (ETH_P_PHONET) which is out of the Ethernet type range. They can
> +only send and receive Phonet packets.
> +
> +The virtual TUN tunnel device driver can also be used for Phonet. This
> +requires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case,
> +there is no link-layer header, so there is no Phonet media type byte.
>  
>  Note that Phonet interfaces are not allowed to re-order packets, so
>  only the (default) Linux FIFO qdisc should be used with them.

Thanks,
~Randy

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2008-09-24 15:46 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-22 15:45 [PATCH 00/11] PhoNet protocols stack v2 Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 01/11] Phonet global definitions Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 02/11] Phonet: PF_PHONET protocol family support Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 03/11] Phonet: add CONFIG_PHONET Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 04/11] Phonet: network device and address handling Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 05/11] Phonet: Netlink interface Rémi Denis-Courmont
2008-09-23 12:10   ` Thomas Graf
2008-09-24 11:30     ` Rémi Denis-Courmont
2008-09-24 13:23       ` Thomas Graf
2008-09-22 15:47 ` [PATCH 06/11] Phonet: common socket glue Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 07/11] Phonet: Phonet datagram transport protocol Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 08/11] Phonet: provide MAC header operations Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 09/11] Phonet: proc interface for port range Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 10/11] Phonet: emit errors when a packet cannot be delivered locally Rémi Denis-Courmont
2008-09-22 15:47 ` [PATCH 11/11] Phonet: kernel documentation Rémi Denis-Courmont
2008-09-23 21:43   ` Randy Dunlap
2008-09-24 12:15     ` [PATCH] Phonet: improve documentation Rémi Denis-Courmont
2008-09-24 15:45       ` Randy Dunlap
2008-09-23  3:16 ` [PATCH 00/11] PhoNet protocols stack v2 David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).