From: David Ahern <dsa@cumulusnetworks.com>
To: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>,
netdev@vger.kernel.org
Cc: shm@cumulusnetworks.com, roopa@cumulusnetworks.com,
gospo@cumulusnetworks.com, jtoppins@cumulusnetworks.com,
ddutt@cumulusnetworks.com, hannes@stressinduktion.org,
nicolas.dichtel@6wind.com, stephen@networkplumber.org,
hadi@mojatatu.com, ebiederm@xmission.com, davem@davemloft.net
Subject: Re: [RFC net-next 3/6] net: Introduce VRF device driver - v2
Date: Mon, 06 Jul 2015 10:46:59 -0600 [thread overview]
Message-ID: <559AB103.1070603@cumulusnetworks.com> (raw)
In-Reply-To: <559AAEE1.2050105@cumulusnetworks.com>
On 7/6/15 10:37 AM, Nikolay Aleksandrov wrote:
>> +static int vrf_add_slave(struct net_device *dev,
>> + struct net_device *port_dev)
>> +{
>> + if (!dev || !port_dev || dev_net(dev) != dev_net(port_dev))
>> + return -ENODEV;
>> +
>> + if (!vrf_is_master(port_dev) && !vrf_is_slave(port_dev)) {
>> + struct slave *s = kzalloc(sizeof(*s), GFP_KERNEL);
>> + struct net_vrf *vrf = netdev_priv(dev);
>> + struct slave_queue *queue = &vrf->queue;
>> + bool is_running = netif_running(port_dev);
>> + unsigned int flags = port_dev->flags;
>> + int ret;
>> +
>> + if (!s)
>> + return -ENOMEM;
>> +
>> + s->dev = port_dev;
>> +
>> + spin_lock_bh(&queue->lock);
>> + __vrf_insert_slave(queue, s, dev);
>> + spin_unlock_bh(&queue->lock);
>> +
>> + port_dev->vrf_ptr = kmalloc(sizeof(*port_dev->vrf_ptr),
>> + GFP_KERNEL);
>> + if (!port_dev->vrf_ptr)
>> + return -ENOMEM;
> ^^^^^^^^^
> I believe you'll have a slave in the list with inconsistent state which could
> even lead to null ptr derefernce if vrf_ptr is used, also __vrf_insert_slave
> does dev_hold so the dev refcnt will be incorrect as well.
Right. Good catch, will fix.
>
>> +
>> + port_dev->vrf_ptr->ifindex = dev->ifindex;
>> + port_dev->vrf_ptr->tb_id = vrf->tb_id;
>> +
>> + /* register the packet handler for slave ports */
>> + ret = netdev_rx_handler_register(port_dev, vrf_handle_frame,
>> + (void *)dev);
>> + if (ret) {
>> + netdev_err(port_dev,
>> + "Device %s failed to register rx_handler\n",
>> + port_dev->name);
>> + kfree(port_dev->vrf_ptr);
>> + kfree(s);
>> + return ret;
> ^^^^^^^^^^
> The slave is being freed while on the list here, device's refcnt will be wrong etc.
ack. Will fix.
>
>> + }
>> +
>> + if (is_running) {
>> + ret = dev_change_flags(port_dev, flags & ~IFF_UP);
>> + if (ret < 0)
>> + goto out_fail;
>> + }
>> +
>> + ret = netdev_master_upper_dev_link(port_dev, dev);
>> + if (ret < 0)
>> + goto out_fail;
>> +
>> + if (is_running) {
>> + ret = dev_change_flags(port_dev, flags);
>> + if (ret < 0)
>> + goto out_fail;
>> + }
>> +
>> + port_dev->flags |= IFF_SLAVE;
>> +
>> + return 0;
>> +
>> +out_fail:
>> + spin_lock_bh(&queue->lock);
>> + __vrf_kill_slave(queue, s);
>> + spin_unlock_bh(&queue->lock);
>
> __vrf_kill_slave() doesn't do upper device unlink and the device can be linked
> if we fail in the dev_change_flags above.
will fix.
>
>> +
>> + return ret;
>> + }
>> +
>> + return -EINVAL;
>> +}
> ^^^^
> In my opinion the structure of the above function should change to something more
> straightforward with proper exit labels and cleanup upon failure, also a level of
> indentation can be avoided.
Sure. The indentation comes after the pointer checks so locals can be
intialized when declared. Will work on the clean up/simplification for
next rev.
>
>> +
>> +static int vrf_del_slave(struct net_device *dev,
>> + struct net_device *port_dev)
>> +{
>> + struct net_vrf *vrf = netdev_priv(dev);
>> + struct slave_queue *queue = &vrf->queue;
>> + struct slave *slave = __vrf_find_slave_dev(queue, port_dev);
>> + bool is_running = netif_running(port_dev);
>> + unsigned int flags = port_dev->flags;
>> + int ret = 0;
>
> ret seems unused/unchecked in this function
It is used but not checked. I struggled with what to do on the error
path. Do we want netdev_err() on a failure?
>
>> +
>> + if (!slave)
>> + return -EINVAL;
>> +
>> + if (is_running)
>> + ret = dev_change_flags(port_dev, flags & ~IFF_UP);
>> +
>> + spin_lock_bh(&queue->lock);
>> + __vrf_kill_slave(queue, slave);
>> + spin_unlock_bh(&queue->lock);
>> +
>> + netdev_upper_dev_unlink(port_dev, dev);
>> +
>> + if (is_running)
>> + ret = dev_change_flags(port_dev, flags);
>> +
>> + return 0;
>> +}
>> +
>> +static int vrf_dev_init(struct net_device *dev)
>> +{
>> + struct net_vrf *vrf = netdev_priv(dev);
>> +
>> + spin_lock_init(&vrf->queue.lock);
>> + INIT_LIST_HEAD(&vrf->queue.all_slaves);
>> + vrf->queue.master_dev = dev;
>> +
>> + dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
>> + dev->flags = IFF_MASTER | IFF_NOARP;
>> + if (!dev->dstats)
>> + return -ENOMEM;
> ^^^^^
> nit: I'd suggest moving the check after the allocation
agreed.
David
next prev parent reply other threads:[~2015-07-06 16:47 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-06 15:03 [RFC net-next 0/6] Proposal for VRF-lite - v2 David Ahern
2015-07-06 15:03 ` [RFC net-next 1/6] fib: export symbols David Ahern
2015-07-06 15:03 ` [RFC net-next 2/6] net: Preparation for vrf device David Ahern
2015-07-08 8:37 ` Nicolas Dichtel
2015-07-08 8:40 ` Nicolas Dichtel
2015-07-08 16:10 ` David Ahern
2015-07-06 15:03 ` [RFC net-next 3/6] net: Introduce VRF device driver - v2 David Ahern
2015-07-06 15:42 ` Nicolas Dichtel
2015-07-06 16:37 ` Nikolay Aleksandrov
2015-07-06 16:46 ` David Ahern [this message]
2015-07-08 9:27 ` Nicolas Dichtel
2015-07-08 16:38 ` David Ahern
2015-07-08 18:34 ` Sowmini Varadhan
2015-07-09 17:19 ` David Ahern
2015-07-09 17:28 ` Sowmini Varadhan
2015-07-10 1:36 ` Eric W. Biederman
2015-07-10 2:12 ` David Ahern
2015-07-10 3:55 ` Eric W. Biederman
2015-07-10 4:20 ` David Ahern
2015-07-10 4:56 ` Eric W. Biederman
2015-07-10 18:42 ` David Ahern
2015-07-10 2:39 ` David Ahern
2015-07-10 3:28 ` Sowmini Varadhan
2015-07-10 3:44 ` David Ahern
2015-07-06 15:03 ` [RFC net-next 4/6] net: Modifications to ipv4 stack for VRF devices David Ahern
2015-07-06 15:03 ` [RFC net-next 5/6] net: Add sk_bind_dev_if to task_struct David Ahern
2015-07-06 15:03 ` [RFC net-next 6/6] net: Add chvrf command David Ahern
2015-07-06 15:03 ` [RFC PATCH] iproute2: Add support for VRF device David Ahern
2015-07-06 15:40 ` [RFC net-next 0/6] Proposal for VRF-lite - v2 Nicolas Dichtel
2015-07-06 17:53 ` Shrijeet Mukherjee
2015-07-08 9:30 ` Nicolas Dichtel
2015-07-10 5:14 ` Scott Feldman
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=559AB103.1070603@cumulusnetworks.com \
--to=dsa@cumulusnetworks.com \
--cc=davem@davemloft.net \
--cc=ddutt@cumulusnetworks.com \
--cc=ebiederm@xmission.com \
--cc=gospo@cumulusnetworks.com \
--cc=hadi@mojatatu.com \
--cc=hannes@stressinduktion.org \
--cc=jtoppins@cumulusnetworks.com \
--cc=netdev@vger.kernel.org \
--cc=nicolas.dichtel@6wind.com \
--cc=nikolay@cumulusnetworks.com \
--cc=roopa@cumulusnetworks.com \
--cc=shm@cumulusnetworks.com \
--cc=stephen@networkplumber.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.