Esempio n. 1
0
static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct xenvif *vif = netdev_priv(dev);
	struct xenvif_queue *queue = NULL;
	unsigned int num_queues;
	u16 index;
	struct xenvif_rx_cb *cb;

	BUG_ON(skb->dev != dev);

	/* Drop the packet if queues are not set up.
	 * This handler should be called inside an RCU read section
	 * so we don't need to enter it here explicitly.
	 */
	num_queues = READ_ONCE(vif->num_queues);
	if (num_queues < 1)
		goto drop;

	/* Obtain the queue to be used to transmit this packet */
	index = skb_get_queue_mapping(skb);
	if (index >= num_queues) {
		pr_warn_ratelimited("Invalid queue %hu for packet on interface %s\n.",
				    index, vif->dev->name);
		index %= num_queues;
	}
	queue = &vif->queues[index];

	/* Drop the packet if queue is not ready */
	if (queue->task == NULL ||
	    queue->dealloc_task == NULL ||
	    !xenvif_schedulable(vif))
		goto drop;

	if (vif->multicast_control && skb->pkt_type == PACKET_MULTICAST) {
		struct ethhdr *eth = (struct ethhdr *)skb->data;

		if (!xenvif_mcast_match(vif, eth->h_dest))
			goto drop;
	}

	cb = XENVIF_RX_CB(skb);
	cb->expires = jiffies + vif->drain_timeout;

	/* If there is no hash algorithm configured then make sure there
	 * is no hash information in the socket buffer otherwise it
	 * would be incorrectly forwarded to the frontend.
	 */
	if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
		skb_clear_hash(skb);

	xenvif_rx_queue_tail(queue, skb);
	xenvif_kick_thread(queue);

	return NETDEV_TX_OK;

 drop:
	vif->dev->stats.tx_dropped++;
	dev_kfree_skb(skb);
	return NETDEV_TX_OK;
}
Esempio n. 2
0
static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
    struct xenvif *vif = netdev_priv(dev);
    struct xenvif_queue *queue = NULL;
    unsigned int num_queues = vif->num_queues;
    u16 index;
    struct xenvif_rx_cb *cb;

    BUG_ON(skb->dev != dev);

    /* Drop the packet if queues are not set up */
    if (num_queues < 1)
        goto drop;

    /* Obtain the queue to be used to transmit this packet */
    index = skb_get_queue_mapping(skb);
    if (index >= num_queues) {
        pr_warn_ratelimited("Invalid queue %hu for packet on interface %s\n.",
                            index, vif->dev->name);
        index %= num_queues;
    }
    queue = &vif->queues[index];

    /* Drop the packet if queue is not ready */
    if (queue->task == NULL ||
            queue->dealloc_task == NULL ||
            !xenvif_schedulable(vif))
        goto drop;

    if (vif->multicast_control && skb->pkt_type == PACKET_MULTICAST) {
        struct ethhdr *eth = (struct ethhdr *)skb->data;

        if (!xenvif_mcast_match(vif, eth->h_dest))
            goto drop;
    }

    cb = XENVIF_RX_CB(skb);
    cb->expires = jiffies + vif->drain_timeout;

    xenvif_rx_queue_tail(queue, skb);
    xenvif_kick_thread(queue);

    return NETDEV_TX_OK;

drop:
    vif->dev->stats.tx_dropped++;
    dev_kfree_skb(skb);
    return NETDEV_TX_OK;
}