* [PATCH 0/5] Phonet: basic routing support
@ 2009-09-15 11:30 Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 1/5] Phonet: error on broadcast sending (unimplemented) Rémi Denis-Courmont
2009-09-15 21:22 ` [PATCH 0/5] Phonet: basic routing support David Miller
0 siblings, 2 replies; 7+ messages in thread
From: Rémi Denis-Courmont @ 2009-09-15 11:30 UTC (permalink / raw)
To: netdev
Hello,
This small patch series adds simplistic routing support to the Phonet
stack. Usually, there is an "upstream" interface to the Phonet modem.
However, if Linux runs on an embedded USB gadget, we have two interfaces in
the same namespace:
- an internal interface to the modem (e.g. OMAP SSI bus), and
- an external interface to the USB host (CDC Phonet).
Patches follow.
include/linux/phonet.h | 1
include/net/phonet/pn_dev.h | 6 ++
net/phonet/af_phonet.c | 55 ++++++++++++++++--
net/phonet/pn_dev.c | 131
+++++++++++++++++++++++++++++++++++++++++---
net/phonet/pn_netlink.c | 130
+++++++++++++++++++++++++++++++++++++++++++
5 files changed, 312 insertions(+), 11 deletions(-)
I am not sure if feature patches are still allowed. If not, I can just
repost this at a more convenient time.
--
Rémi Denis-Courmont
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/5] Phonet: error on broadcast sending (unimplemented)
2009-09-15 11:30 [PATCH 0/5] Phonet: basic routing support Rémi Denis-Courmont
@ 2009-09-15 11:32 ` Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 2/5] Phonet: routing table backend Rémi Denis-Courmont
2009-09-15 21:22 ` [PATCH 0/5] Phonet: basic routing support David Miller
1 sibling, 1 reply; 7+ messages in thread
From: Rémi Denis-Courmont @ 2009-09-15 11:32 UTC (permalink / raw)
To: netdev; +Cc: Rémi Denis-Courmont
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
include/linux/phonet.h | 1 +
net/phonet/af_phonet.c | 6 ++++++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index 1ef5a07..e5126cf 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -38,6 +38,7 @@
#define PNPIPE_IFINDEX 2
#define PNADDR_ANY 0
+#define PNADDR_BROADCAST 0xFC
#define PNPORT_RESOURCE_ROUTING 0
/* Values for PNPIPE_ENCAP option */
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index a662e62..f60c0c2 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -168,6 +168,12 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
goto drop;
}
+ /* Broadcast sending is not implemented */
+ if (pn_addr(dst) == PNADDR_BROADCAST) {
+ err = -EOPNOTSUPP;
+ goto drop;
+ }
+
skb_reset_transport_header(skb);
WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
skb_push(skb, sizeof(struct phonethdr));
--
1.6.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] Phonet: routing table backend
2009-09-15 11:32 ` [PATCH 1/5] Phonet: error on broadcast sending (unimplemented) Rémi Denis-Courmont
@ 2009-09-15 11:32 ` Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 3/5] Phonet: routing table Netlink interface Rémi Denis-Courmont
0 siblings, 1 reply; 7+ messages in thread
From: Rémi Denis-Courmont @ 2009-09-15 11:32 UTC (permalink / raw)
To: netdev; +Cc: Rémi Denis-Courmont
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
The Phonet "universe" only has 64 addresses, so we keep a trivial flat
routing table.
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
include/net/phonet/pn_dev.h | 5 ++
net/phonet/pn_dev.c | 100 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 99 insertions(+), 6 deletions(-)
diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h
index 44c923c..87b5d81 100644
--- a/include/net/phonet/pn_dev.h
+++ b/include/net/phonet/pn_dev.h
@@ -47,6 +47,11 @@ u8 phonet_address_get(struct net_device *dev, u8 addr);
int phonet_address_lookup(struct net *net, u8 addr);
void phonet_address_notify(int event, struct net_device *dev, u8 addr);
+int phonet_route_add(struct net_device *dev, u8 daddr);
+int phonet_route_del(struct net_device *dev, u8 daddr);
+struct net_device *phonet_route_get(struct net *net, u8 daddr);
+struct net_device *phonet_route_output(struct net *net, u8 daddr);
+
#define PN_NO_ADDR 0xff
extern const struct file_operations pn_sock_seq_fops;
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 5f42f30..71fffa5 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -33,8 +33,14 @@
#include <net/netns/generic.h>
#include <net/phonet/pn_dev.h>
+struct phonet_routes {
+ spinlock_t lock;
+ struct net_device *table[64];
+};
+
struct phonet_net {
struct phonet_device_list pndevs;
+ struct phonet_routes routes;
};
int phonet_net_id;
@@ -154,10 +160,11 @@ int phonet_address_del(struct net_device *dev, u8 addr)
}
/* Gets a source address toward a destination, through a interface. */
-u8 phonet_address_get(struct net_device *dev, u8 addr)
+u8 phonet_address_get(struct net_device *dev, u8 daddr)
{
struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
struct phonet_device *pnd;
+ u8 saddr;
spin_lock_bh(&pndevs->lock);
pnd = __phonet_get(dev);
@@ -165,12 +172,26 @@ u8 phonet_address_get(struct net_device *dev, u8 addr)
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;
+ if (test_bit(daddr >> 2, pnd->addrs))
+ saddr = daddr;
+ else
+ saddr = find_first_bit(pnd->addrs, 64) << 2;
} else
- addr = PN_NO_ADDR;
+ saddr = PN_NO_ADDR;
spin_unlock_bh(&pndevs->lock);
- return addr;
+
+ if (saddr == PN_NO_ADDR) {
+ /* Fallback to another device */
+ struct net_device *def_dev;
+
+ def_dev = phonet_device_get(dev_net(dev));
+ if (def_dev) {
+ if (def_dev != dev)
+ saddr = phonet_address_get(def_dev, daddr);
+ dev_put(def_dev);
+ }
+ }
+ return saddr;
}
int phonet_address_lookup(struct net *net, u8 addr)
@@ -246,7 +267,7 @@ static struct notifier_block phonet_device_notifier = {
/* Per-namespace Phonet devices handling */
static int phonet_init_net(struct net *net)
{
- struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL);
+ struct phonet_net *pnn = kzalloc(sizeof(*pnn), GFP_KERNEL);
if (!pnn)
return -ENOMEM;
@@ -257,6 +278,7 @@ static int phonet_init_net(struct net *net)
INIT_LIST_HEAD(&pnn->pndevs.list);
spin_lock_init(&pnn->pndevs.lock);
+ spin_lock_init(&pnn->routes.lock);
net_assign_generic(net, phonet_net_id, pnn);
return 0;
}
@@ -300,3 +322,69 @@ void phonet_device_exit(void)
unregister_netdevice_notifier(&phonet_device_notifier);
unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops);
}
+
+int phonet_route_add(struct net_device *dev, u8 daddr)
+{
+ struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id);
+ struct phonet_routes *routes = &pnn->routes;
+ int err = -EEXIST;
+
+ daddr = daddr >> 2;
+ spin_lock_bh(&routes->lock);
+ if (routes->table[daddr] == NULL) {
+ routes->table[daddr] = dev;
+ dev_hold(dev);
+ err = 0;
+ }
+ spin_unlock_bh(&routes->lock);
+ return err;
+}
+
+int phonet_route_del(struct net_device *dev, u8 daddr)
+{
+ struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id);
+ struct phonet_routes *routes = &pnn->routes;
+ int err = -ENOENT;
+
+ daddr = daddr >> 2;
+ spin_lock_bh(&routes->lock);
+ if (dev == routes->table[daddr]) {
+ routes->table[daddr] = NULL;
+ dev_put(dev);
+ err = 0;
+ }
+ spin_unlock_bh(&routes->lock);
+ return err;
+}
+
+struct net_device *phonet_route_get(struct net *net, u8 daddr)
+{
+ struct phonet_net *pnn = net_generic(net, phonet_net_id);
+ struct phonet_routes *routes = &pnn->routes;
+ struct net_device *dev;
+
+ ASSERT_RTNL(); /* no need to hold the device */
+
+ daddr >>= 2;
+ spin_lock_bh(&routes->lock);
+ dev = routes->table[daddr];
+ spin_unlock_bh(&routes->lock);
+ return dev;
+}
+
+struct net_device *phonet_route_output(struct net *net, u8 daddr)
+{
+ struct phonet_net *pnn = net_generic(net, phonet_net_id);
+ struct phonet_routes *routes = &pnn->routes;
+ struct net_device *dev;
+
+ spin_lock_bh(&routes->lock);
+ dev = routes->table[daddr >> 2];
+ if (dev)
+ dev_hold(dev);
+ spin_unlock_bh(&routes->lock);
+
+ if (!dev)
+ dev = phonet_device_get(net); /* Default route */
+ return dev;
+}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] Phonet: routing table Netlink interface
2009-09-15 11:32 ` [PATCH 2/5] Phonet: routing table backend Rémi Denis-Courmont
@ 2009-09-15 11:32 ` Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 4/5] Phonet: route outgoing packets Rémi Denis-Courmont
0 siblings, 1 reply; 7+ messages in thread
From: Rémi Denis-Courmont @ 2009-09-15 11:32 UTC (permalink / raw)
To: netdev; +Cc: Rémi Denis-Courmont
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
include/net/phonet/pn_dev.h | 1 +
net/phonet/pn_dev.c | 31 ++++++++++
net/phonet/pn_netlink.c | 130 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 162 insertions(+), 0 deletions(-)
diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h
index 87b5d81..afa7def 100644
--- a/include/net/phonet/pn_dev.h
+++ b/include/net/phonet/pn_dev.h
@@ -49,6 +49,7 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr);
int phonet_route_add(struct net_device *dev, u8 daddr);
int phonet_route_del(struct net_device *dev, u8 daddr);
+void rtm_phonet_notify(int event, struct net_device *dev, u8 dst);
struct net_device *phonet_route_get(struct net *net, u8 daddr);
struct net_device *phonet_route_output(struct net *net, u8 daddr);
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 71fffa5..6d64fda 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -240,6 +240,27 @@ static int phonet_device_autoconf(struct net_device *dev)
return 0;
}
+static void phonet_route_autodel(struct net_device *dev)
+{
+ struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id);
+ unsigned i;
+ DECLARE_BITMAP(deleted, 64);
+
+ /* Remove left-over Phonet routes */
+ bitmap_zero(deleted, 64);
+ spin_lock_bh(&pnn->routes.lock);
+ for (i = 0; i < 64; i++)
+ if (dev == pnn->routes.table[i]) {
+ set_bit(i, deleted);
+ pnn->routes.table[i] = NULL;
+ dev_put(dev);
+ }
+ spin_unlock_bh(&pnn->routes.lock);
+ for (i = find_first_bit(deleted, 64); i < 64;
+ i = find_next_bit(deleted, 64, i + 1))
+ rtm_phonet_notify(RTM_DELROUTE, dev, i);
+}
+
/* notify Phonet of device events */
static int phonet_device_notify(struct notifier_block *me, unsigned long what,
void *arg)
@@ -253,6 +274,7 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what,
break;
case NETDEV_UNREGISTER:
phonet_device_destroy(dev);
+ phonet_route_autodel(dev);
break;
}
return 0;
@@ -287,10 +309,19 @@ static void phonet_exit_net(struct net *net)
{
struct phonet_net *pnn = net_generic(net, phonet_net_id);
struct net_device *dev;
+ unsigned i;
rtnl_lock();
for_each_netdev(net, dev)
phonet_device_destroy(dev);
+
+ for (i = 0; i < 64; i++) {
+ dev = pnn->routes.table[i];
+ if (dev) {
+ rtm_phonet_notify(RTM_DELROUTE, dev, i);
+ dev_put(dev);
+ }
+ }
rtnl_unlock();
proc_net_remove(net, "phonet");
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index d21fd35..d8f5d3f 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -29,6 +29,8 @@
#include <net/sock.h>
#include <net/phonet/pn_dev.h>
+/* Device address handling */
+
static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
u32 pid, u32 seq, int event);
@@ -160,6 +162,131 @@ out:
return skb->len;
}
+/* Routes handling */
+
+static int fill_route(struct sk_buff *skb, struct net_device *dev, u8 dst,
+ u32 pid, u32 seq, int event)
+{
+ struct rtmsg *rtm;
+ struct nlmsghdr *nlh;
+
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), 0);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+ rtm = nlmsg_data(nlh);
+ rtm->rtm_family = AF_PHONET;
+ rtm->rtm_dst_len = 6;
+ rtm->rtm_src_len = 0;
+ rtm->rtm_tos = 0;
+ rtm->rtm_table = RT_TABLE_MAIN;
+ rtm->rtm_protocol = RTPROT_STATIC;
+ rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+ rtm->rtm_type = RTN_UNICAST;
+ rtm->rtm_flags = 0;
+ NLA_PUT_U8(skb, RTA_DST, dst);
+ NLA_PUT_U32(skb, RTA_OIF, dev->ifindex);
+ return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
+void rtm_phonet_notify(int event, struct net_device *dev, u8 dst)
+{
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
+ nla_total_size(1) + nla_total_size(4), GFP_KERNEL);
+ if (skb == NULL)
+ goto errout;
+ err = fill_route(skb, dev, dst, 0, 0, event);
+ if (err < 0) {
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
+ rtnl_notify(skb, dev_net(dev), 0,
+ RTNLGRP_PHONET_ROUTE, NULL, GFP_KERNEL);
+ return;
+errout:
+ if (err < 0)
+ rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_ROUTE, err);
+}
+
+static const struct nla_policy rtm_phonet_policy[RTA_MAX+1] = {
+ [RTA_DST] = { .type = NLA_U8 },
+ [RTA_OIF] = { .type = NLA_U32 },
+};
+
+static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
+{
+ struct net *net = sock_net(skb->sk);
+ struct nlattr *tb[RTA_MAX+1];
+ struct net_device *dev;
+ struct rtmsg *rtm;
+ int err;
+ u8 dst;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ ASSERT_RTNL();
+
+ err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_phonet_policy);
+ if (err < 0)
+ return err;
+
+ rtm = nlmsg_data(nlh);
+ if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_type != RTN_UNICAST)
+ return -EINVAL;
+ if (tb[RTA_DST] == NULL || tb[RTA_OIF] == NULL)
+ return -EINVAL;
+ dst = nla_get_u8(tb[RTA_DST]);
+ if (dst & 3) /* Phonet addresses only have 6 high-order bits */
+ return -EINVAL;
+
+ dev = __dev_get_by_index(net, nla_get_u32(tb[RTA_OIF]));
+ if (dev == NULL)
+ return -ENODEV;
+
+ if (nlh->nlmsg_type == RTM_NEWROUTE)
+ err = phonet_route_add(dev, dst);
+ else
+ err = phonet_route_del(dev, dst);
+ if (!err)
+ rtm_phonet_notify(nlh->nlmsg_type, dev, dst);
+ return err;
+}
+
+static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct net *net = sock_net(skb->sk);
+ u8 addr, addr_idx = 0, addr_start_idx = cb->args[0];
+
+ for (addr = 0; addr < 64; addr++) {
+ struct net_device *dev;
+
+ dev = phonet_route_get(net, addr << 2);
+ if (!dev)
+ continue;
+
+ if (addr_idx++ < addr_start_idx)
+ continue;
+ if (fill_route(skb, dev, addr << 2, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWROUTE))
+ goto out;
+ }
+
+out:
+ cb->args[0] = addr_idx;
+ cb->args[1] = 0;
+
+ return skb->len;
+}
+
int __init phonet_netlink_register(void)
{
int err = __rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
@@ -169,5 +296,8 @@ int __init phonet_netlink_register(void)
/* Further __rtnl_register() cannot fail */
__rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
__rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
+ __rtnl_register(PF_PHONET, RTM_NEWROUTE, route_doit, NULL);
+ __rtnl_register(PF_PHONET, RTM_DELROUTE, route_doit, NULL);
+ __rtnl_register(PF_PHONET, RTM_GETROUTE, NULL, route_dumpit);
return 0;
}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] Phonet: route outgoing packets
2009-09-15 11:32 ` [PATCH 3/5] Phonet: routing table Netlink interface Rémi Denis-Courmont
@ 2009-09-15 11:32 ` Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 5/5] Phonet: forward incoming packets Rémi Denis-Courmont
0 siblings, 1 reply; 7+ messages in thread
From: Rémi Denis-Courmont @ 2009-09-15 11:32 UTC (permalink / raw)
To: netdev; +Cc: Rémi Denis-Courmont
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
net/phonet/af_phonet.c | 17 ++++++++++++-----
1 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 013f471..f0ef6f8 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -190,9 +190,8 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
skb->priority = 0;
skb->dev = dev;
- if (pn_addr(src) == pn_addr(dst)) {
+ if (skb->pkt_type == PACKET_LOOPBACK) {
skb_reset_mac_header(skb);
- skb->pkt_type = PACKET_LOOPBACK;
skb_orphan(skb);
if (irq)
netif_rx(skb);
@@ -222,6 +221,9 @@ static int pn_raw_send(const void *data, int len, struct net_device *dev,
if (skb == NULL)
return -ENOMEM;
+ if (phonet_address_lookup(dev_net(dev), pn_addr(dst)) == 0)
+ skb->pkt_type = PACKET_LOOPBACK;
+
skb_reserve(skb, MAX_PHONET_HEADER);
__skb_put(skb, len);
skb_copy_to_linear_data(skb, data, len);
@@ -235,6 +237,7 @@ static int pn_raw_send(const void *data, int len, struct net_device *dev,
int pn_skb_send(struct sock *sk, struct sk_buff *skb,
const struct sockaddr_pn *target)
{
+ struct net *net = sock_net(sk);
struct net_device *dev;
struct pn_sock *pn = pn_sk(sk);
int err;
@@ -243,9 +246,13 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb,
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));
+ dev = dev_get_by_index(net, sk->sk_bound_dev_if);
+ else if (phonet_address_lookup(net, daddr) == 0) {
+ dev = phonet_device_get(net);
+ skb->pkt_type = PACKET_LOOPBACK;
+ } else
+ dev = phonet_route_output(net, daddr);
+
if (!dev || !(dev->flags & IFF_UP))
goto drop;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] Phonet: forward incoming packets
2009-09-15 11:32 ` [PATCH 4/5] Phonet: route outgoing packets Rémi Denis-Courmont
@ 2009-09-15 11:32 ` Rémi Denis-Courmont
0 siblings, 0 replies; 7+ messages in thread
From: Rémi Denis-Courmont @ 2009-09-15 11:32 UTC (permalink / raw)
To: netdev; +Cc: Rémi Denis-Courmont
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
net/phonet/af_phonet.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index f0ef6f8..e69c915 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -394,8 +394,40 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
send_obj_unreachable(skb);
send_reset_indications(skb);
}
+ } else if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+ goto out; /* Race between address deletion and loopback */
+ else {
+ /* Phonet packet routing */
+ struct net_device *out_dev;
+
+ out_dev = phonet_route_output(net, pn_sockaddr_get_addr(&sa));
+ if (!out_dev) {
+ LIMIT_NETDEBUG(KERN_WARNING"No Phonet route to %02X\n",
+ pn_sockaddr_get_addr(&sa));
+ goto out;
+ }
+
+ __skb_push(skb, sizeof(struct phonethdr));
+ skb->dev = out_dev;
+ if (out_dev == dev) {
+ LIMIT_NETDEBUG(KERN_ERR"Phonet loop to %02X on %s\n",
+ pn_sockaddr_get_addr(&sa), dev->name);
+ goto out_dev;
+ }
+ /* Some drivers (e.g. TUN) do not allocate HW header space */
+ if (skb_cow_head(skb, out_dev->hard_header_len))
+ goto out_dev;
+
+ if (dev_hard_header(skb, out_dev, ETH_P_PHONET, NULL, NULL,
+ skb->len) < 0)
+ goto out_dev;
+ dev_queue_xmit(skb);
+ dev_put(out_dev);
+ return NET_RX_SUCCESS;
}
+out_dev:
+ dev_put(skb->dev);
out:
kfree_skb(skb);
return NET_RX_DROP;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 0/5] Phonet: basic routing support
2009-09-15 11:30 [PATCH 0/5] Phonet: basic routing support Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 1/5] Phonet: error on broadcast sending (unimplemented) Rémi Denis-Courmont
@ 2009-09-15 21:22 ` David Miller
1 sibling, 0 replies; 7+ messages in thread
From: David Miller @ 2009-09-15 21:22 UTC (permalink / raw)
To: remi; +Cc: netdev
From: Rémi Denis-Courmont <remi@remlab.net>
Date: Tue, 15 Sep 2009 13:30:19 +0200
> I am not sure if feature patches are still allowed. If not, I can just
> repost this at a more convenient time.
Please resend these when net-next-2.6 opens back up.
Thank you.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-09-15 21:22 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-15 11:30 [PATCH 0/5] Phonet: basic routing support Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 1/5] Phonet: error on broadcast sending (unimplemented) Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 2/5] Phonet: routing table backend Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 3/5] Phonet: routing table Netlink interface Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 4/5] Phonet: route outgoing packets Rémi Denis-Courmont
2009-09-15 11:32 ` [PATCH 5/5] Phonet: forward incoming packets Rémi Denis-Courmont
2009-09-15 21:22 ` [PATCH 0/5] Phonet: basic routing support 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).