* For example, consider a packet that holds onto resources belonging to the
* guest for which it is queued (e.g., packet received on vif1.0, destined for
* vif1.1 which is not activated in the guest): in this situation the guest
- * will never be destroyed, unless vif1.1 is taken down (which flushes the
- * 'tx_queue').
- *
- * Only set this parameter to non-zero value if you know what you are doing!
+ * will never be destroyed, unless vif1.1 is taken down. To avoid this, we
+ * run a timer (tx_queue_timeout) to drain the queue when the interface is
+ * blocked.
*/
-static unsigned long netbk_queue_length = 0;
+static unsigned long netbk_queue_length = 32;
module_param_named(queue_length, netbk_queue_length, ulong, 0);
static void __netif_up(netif_t *netif)
{
disable_irq(netif->irq);
netif_deschedule_work(netif);
- del_timer_sync(&netif->credit_timeout);
}
static int net_open(struct net_device *dev)
.get_link = ethtool_op_get_link,
};
-netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
+netif_t *netif_alloc(domid_t domid, unsigned int handle)
{
int err = 0, i;
struct net_device *dev;
netif->credit_bytes = netif->remaining_credit = ~0UL;
netif->credit_usec = 0UL;
init_timer(&netif->credit_timeout);
+ /* Initialize 'expires' now: it's used to track the credit window. */
netif->credit_timeout.expires = jiffies;
+ init_timer(&netif->tx_queue_timeout);
+
dev->hard_start_xmit = netif_be_start_xmit;
dev->get_stats = netif_be_get_stats;
dev->open = net_open;
SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
dev->tx_queue_len = netbk_queue_length;
- if (dev->tx_queue_len != 0)
- printk(KERN_WARNING "netbk: WARNING: device '%s' has non-zero "
- "queue length (%lu)!\n", dev->name, dev->tx_queue_len);
-
- for (i = 0; i < ETH_ALEN; i++)
- if (be_mac[i] != 0)
- break;
- if (i == ETH_ALEN) {
- /*
- * Initialise a dummy MAC address. We choose the numerically
- * largest non-broadcast address to prevent the address getting
- * stolen by an Ethernet bridge for STP purposes.
- * (FE:FF:FF:FF:FF:FF)
- */
- memset(dev->dev_addr, 0xFF, ETH_ALEN);
- dev->dev_addr[0] &= ~0x01;
- } else
- memcpy(dev->dev_addr, be_mac, ETH_ALEN);
+
+ /*
+ * Initialise a dummy MAC address. We choose the numerically
+ * largest non-broadcast address to prevent the address getting
+ * stolen by an Ethernet bridge for STP purposes.
+ * (FE:FF:FF:FF:FF:FF)
+ */
+ memset(dev->dev_addr, 0xFF, ETH_ALEN);
+ dev->dev_addr[0] &= ~0x01;
rtnl_lock();
err = register_netdevice(dev);
return err;
}
-static void netif_free(netif_t *netif)
+void netif_disconnect(netif_t *netif)
{
+ if (netif_carrier_ok(netif->dev)) {
+ rtnl_lock();
+ netif_carrier_off(netif->dev);
+ if (netif_running(netif->dev))
+ __netif_down(netif);
+ rtnl_unlock();
+ netif_put(netif);
+ }
+
atomic_dec(&netif->refcnt);
wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
+ del_timer_sync(&netif->credit_timeout);
+ del_timer_sync(&netif->tx_queue_timeout);
+
if (netif->irq)
unbind_from_irqhandler(netif->irq, netif);
free_netdev(netif->dev);
}
-
-void netif_disconnect(netif_t *netif)
-{
- if (netif_carrier_ok(netif->dev)) {
- rtnl_lock();
- netif_carrier_off(netif->dev);
- if (netif_running(netif->dev))
- __netif_down(netif);
- rtnl_unlock();
- netif_put(netif);
- }
- netif_free(netif);
-}