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; }
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; }