From: Ben Greear <greearb@candelatech.com>
To: "Eric W. Biederman" <ebiederm@xmission.com>,
NetDev <netdev@vger.kernel.org>
Subject: Re: [PATCH RFC 31/31] net: Add etun driver
Date: Thu, 25 Jan 2007 11:47:24 -0800 [thread overview]
Message-ID: <45B9094C.3030902@candelatech.com> (raw)
In-Reply-To: <11697516404048-git-send-email-ebiederm@xmission.com>
Eric W. Biederman wrote:
> From: Eric W. Biederman <ebiederm@xmission.com> - unquoted
>
> etun is a simple two headed tunnel driver that at the link layer
> looks like ethernet. It's target audience is communicating
> between network namespaces but it is general enough it may
> have other uses as well.
>
This looks almost identical to my redir-dev module. Which is
fine..I don't really care which gets into the kernel so long as
one of them does...
Comments and questions are inline below.
> +/*
> + * The higher levels take care of making this non-reentrant (it's
> + * called with bh's disabled).
> + */
> +static int etun_xmit(struct sk_buff *skb, struct net_device *tx_dev)
> +{
> + struct etun_info *tx_info = tx_dev->priv;
> + struct net_device *rx_dev = tx_info->rx_dev;
> + struct etun_info *rx_info = rx_dev->priv;
> +
> + tx_info->stats.tx_packets++;
> + tx_info->stats.tx_bytes += skb->len;
> +
> + /* Drop the skb state that was needed to get here */
> + skb_orphan(skb);
> + if (skb->dst)
> + skb->dst = dst_pop(skb->dst); /* Allow for smart routing */
I ended up setting dst to NULL. What does the dst_pop() accomplish?
> +
> + /* Switch to the receiving device */
> + skb->pkt_type = PACKET_HOST;
> + skb->protocol = eth_type_trans(skb, rx_dev);
> + skb->dev = rx_dev;
> + skb->ip_summed = CHECKSUM_NONE;
> +
> + /* If both halves agree no checksum is needed */
> + if (tx_dev->features & NETIF_F_NO_CSUM)
> + skb->ip_summed = rx_info->ip_summed;
> +
> + rx_dev->last_rx = jiffies;
Do you need to set tx_dev->trans_start to jiffies as well?
> + rx_info->stats.rx_packets++;
> + rx_info->stats.rx_bytes += skb->len;
I think you need to zero out the skb->tstamp as well. This lets it
be re-calculated when the receive logic of the other device is called.
Otherwise this fails:
rx skb on eth1, delay skb for network emulation, bridge onto etun0, rx on etun1
(time-stamp is still what it was when rx'd on eth1, which is too old.)
> + netif_rx(skb);
> +
> + return 0;
> +}
> +
> +static int etun_open(struct net_device *tx_dev)
> +{
> + struct etun_info *tx_info = tx_dev->priv;
> + struct net_device *rx_dev = tx_info->rx_dev;
> + if (rx_dev->flags & IFF_UP) {
> + netif_carrier_on(tx_dev);
> + netif_carrier_on(rx_dev);
> + }
> + netif_start_queue(tx_dev);
Does this carrier logic keep etun0 from transmitting to
etun1 if etun0 is UP but etun1 is not UP yet?
> + return 0;
> +}
> +
> +static int etun_stop(struct net_device *tx_dev)
> +{
> + struct etun_info *tx_info = tx_dev->priv;
> + struct net_device *rx_dev = tx_info->rx_dev;
> + netif_stop_queue(tx_dev);
> + if (netif_carrier_ok(tx_dev)) {
> + netif_carrier_off(tx_dev);
> + netif_carrier_off(rx_dev);
> + }
> + return 0;
> +}
> +
> +static void etun_set_multicast_list(struct net_device *dev)
> +{
> + /* Nothing sane I can do here */
> + return;
> +}
> +
> +static int etun_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +/* Only allow letters and numbers in an etun device name */
> +static int is_valid_name(const char *name)
> +{
> + const char *ptr;
> + for (ptr = name; *ptr; ptr++) {
> + if (!isalnum(*ptr))
> + return 0;
> + }
> + return 1;
> +}
> +
> +static struct net_device *etun_alloc(net_t net, const char *name)
> +{
> + struct net_device *dev;
> + struct etun_info *info;
> + int err;
> +
> + if (!name || !is_valid_name(name))
> + return ERR_PTR(-EINVAL);
> +
> + dev = alloc_netdev(sizeof(struct etun_info), name, ether_setup);
> + if (!dev)
> + return ERR_PTR(-ENOMEM);
> +
> + info = dev->priv;
> + info->dev = dev;
> + dev->nd_net = net;
> +
> + random_ether_addr(dev->dev_addr);
> + dev->tx_queue_len = 0; /* A queue is silly for a loopback device */
> + dev->hard_start_xmit = etun_xmit;
> + dev->get_stats = etun_get_stats;
> + dev->open = etun_open;
> + dev->stop = etun_stop;
> + dev->set_multicast_list = etun_set_multicast_list;
> + dev->do_ioctl = etun_ioctl;
> + dev->features = NETIF_F_FRAGLIST
> + | NETIF_F_HIGHDMA
> + | NETIF_F_LLTX;
> + dev->flags = IFF_BROADCAST | IFF_MULTICAST |IFF_PROMISC;
> + dev->ethtool_ops = &etun_ethtool_ops;
> + dev->destructor = free_netdev;
You should add ability to change MTU. I believe it is as trivial as this:
int redirdev_change_mtu(struct net_device *dev, int new_mtu) {
dev->mtu = new_mtu;
return 0;
}
> + err = register_netdev(dev);
> + if (err) {
> + free_netdev(dev);
> + dev = ERR_PTR(err);
> + goto out;
> + }
> + netif_carrier_off(dev);
> +out:
> + return dev;
> +}
> +
> +static int etun_alloc_pair(net_t net, const char *name0, const char *name1)
> +{
> + struct net_device *dev0, *dev1;
> + struct etun_info *info0, *info1;
> +
> + dev0 = etun_alloc(net, name0);
> + if (IS_ERR(dev0)) {
> + return PTR_ERR(dev0);
> + }
> + info0 = dev0->priv;
> +
> + dev1 = etun_alloc(net, name1);
> + if (IS_ERR(dev1)) {
> + unregister_netdev(dev0);
> + return PTR_ERR(dev1);
> + }
> + info1 = dev1->priv;
> +
> + dev_hold(dev0);
> + dev_hold(dev1);
> + info0->rx_dev = dev1;
> + info1->rx_dev = dev0;
Can this race such that someone could manage to tx on one of these
devices before you assign the rx_dev? Maybe register-netdev after
this assignment here, instead of in the alloc_etun method above?
> +
> + /* Only place one member of the pair on the list
> + * so I don't confuse list_for_each_entry_safe,
> + * by deleting two list entries at once.
> + */
> + rtnl_lock();
> + list_add(&info0->list, &etun_list);
> + INIT_LIST_HEAD(&info1->list);
> + rtnl_unlock();
> +
> + return 0;
> +}
> +
> +static int etun_unregister_pair(struct net_device *dev0)
> +{
> + struct etun_info *info0, *info1;
> + struct net_device *dev1;
> +
> + ASSERT_RTNL();
> +
> + if (!dev0)
> + return -ENODEV;
> +
> + info0 = dev0->priv;
> + dev1 = info0->rx_dev;
> + info1 = dev1->priv;
> +
> + /* Drop the cross device references */
> + dev_put(dev0);
> + dev_put(dev1);
The devices are still potentially transmitting at this point,
since you have not yet called unregister_netdev?
For redir devices, I dropped association in the 'down' logic,
and re-acquired it lazily. I saved the peer device's name
(not if-index). I am not certain this is required, but I believe
it made locking simpler.
static int redirdev_open(struct net_device *dev) {
struct redirdev* rdd = dev->priv;
rdd->wants_to_run = 1;
if (!rdd->tx_dev) {
rdd->tx_dev = dev_get_by_name(rdd->tx_dev_name);
}
if (!rdd->tx_dev) {
printk("redir: %s Warning: Could not find tx_dev: %s, will try later in redirdev_xmit.\n",
dev->name, rdd->tx_dev_name);
}
printk("redirdev: Starting device: %s\n", dev->name);
netif_start_queue(dev);
return 0;
}
> +
> + /* Remove from the etun list */
> + if (!list_empty(&info0->list))
> + list_del_init(&info0->list);
> + if (!list_empty(&info1->list))
> + list_del_init(&info1->list);
> +
> + unregister_netdevice(dev0);
> + unregister_netdevice(dev1);
> + return 0;
> +}
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
next prev parent reply other threads:[~2007-01-25 19:47 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-01-25 18:55 [RFC PATCH 0/31] An introduction and A path for merging network namespace work Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 1/31] net: Add net_namespace_type.h to allow for per network namespace variables Eric W. Biederman
2007-01-25 20:30 ` Stephen Hemminger
2007-01-25 20:53 ` Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 2/31] net: Implement a place holder network namespace Eric W. Biederman
2007-01-25 19:29 ` Stephen Hemminger
2007-01-25 20:31 ` Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 3/31] net: Add a network namespace parameter to tasks Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 4/31] net: Add a network namespace tag to struct net_device Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 5/31] net: Add a network namespace parameter to struct sock Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 6/31] net: Add a helper to get a reference to the initial network namespace Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 7/31] net: Make /proc/net per " Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 8/31] net: Make /sys/class/net handle multiple network namespaces Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 9/31] net: Implement the per network namespace sysctl infrastructure Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 10/31] net: Make socket creation namespace safe Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 11/31] net: Initialize the network namespace of network devices Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 12/31] net: Make packet reception network namespace safe Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 13/31] net: Make device event notification " Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 14/31] net: Support multiple network namespaces with netlink Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 15/31] net: Make the loopback device per network namespace Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 16/31] net: Make the device list and device lookups per namespace Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 17/31] net: Factor out __dev_alloc_name from dev_alloc_name Eric W. Biederman
2007-03-05 15:29 ` Benjamin Thery
2007-01-25 19:00 ` [PATCH RFC 18/31] net: Implment network device movement between namespaces Eric W. Biederman
2007-02-28 14:35 ` Daniel Lezcano
2007-02-28 15:12 ` Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 19/31] net: sysfs interface support for moving devices between network namespaces Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 20/31] net: Implement CONFIG_NET_NS Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 21/31] net: Implement the guts of the network namespace infrastructure Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 22/31] net: Add network namespace clone support Eric W. Biederman
2007-02-28 14:42 ` Daniel Lezcano
2007-02-28 15:05 ` Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 23/31] net: Modify all rtnetlink methods to only work in the initial namespace Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 24/31] net: Make rtnetlink network namespace aware Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 25/31] net: Make wireless netlink event generation handle multiple network namespaces Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 26/31] net: Make the netlink methods in rtnetlink " Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 27/31] net: Make the xfrm sysctls per network namespace Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 28/31] net: Make the SOMAXCONN sysctl " Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 29/31] net: Make AF_PACKET handle multiple network namespaces Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 30/31] net: Make AF_UNIX per network namespace safe Eric W. Biederman
2007-01-25 19:00 ` [PATCH RFC 31/31] net: Add etun driver Eric W. Biederman
2007-01-25 19:47 ` Ben Greear [this message]
2007-01-25 20:25 ` Eric W. Biederman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=45B9094C.3030902@candelatech.com \
--to=greearb@candelatech.com \
--cc=ebiederm@xmission.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is 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).