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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.