/*
* Virtual network driver for conversing with remote driver backends.
*
* Copyright (c) 2002-2005, K A Fraser
* Copyright (c) 2005, XenSource Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation; or, when distributed
* separately from the Linux kernel or incorporated into other
* software packages, subject to the following license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this source file (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/if_ether.h>
#include <net/tcp.h>
#include <linux/udp.h>
#include <linux/moduleparam.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <net/ip.h>
#include <asm/xen/page.h>
#include <xen/xen.h>
#include <xen/xenbus.h>
#include <xen/events.h>
#include <xen/page.h>
#include <xen/platform_pci.h>
#include <xen/grant_table.h>
#include <xen/interface/io/netif.h>
#include <xen/interface/memory.h>
#include <xen/interface/grant_table.h>
/* Module parameters */
static unsigned int xennet_max_queues;
module_param_named(max_queues, xennet_max_queues, uint, 0644);
MODULE_PARM_DESC(max_queues,
"Maximum number of queues per virtual interface");
static const struct ethtool_ops xennet_ethtool_ops;
struct netfront_cb {
int pull_to;
};
#define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb))
#define RX_COPY_THRESHOLD 256
#define GRANT_INVALID_REF 0
#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
/* Minimum number of Rx slots (includes slot for GSO metadata). */
#define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1)
/* Queue name is interface name with "-qNNN" appended */
#define QUEUE_NAME_SIZE (IFNAMSIZ + 6)
/* IRQ name is queue name with "-tx" or "-rx" appended */
#define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)
struct netfront_stats {
u64 rx_packets;
u64 tx_packets;
u64 rx_bytes;
u64 tx_bytes;
struct u64_stats_sync syncp;
};
struct netfront_info;
struct netfront_queue {
unsigned int id; /* Queue ID, 0-based */
char name[QUEUE_NAME_SIZE]; /* DEVNAME-qN */
struct netfront_info *info;
struct napi_struct napi;
/* Split event channels support, tx_* == rx_* when using
* single event channel.
*/
unsigned int tx_evtchn, rx_evtchn;
unsigned int tx_irq, rx_irq;
/* Only used when split event channels support is enabled */
char tx_irq_name[IRQ_NAME_SIZE]; /* DEVNAME-qN-tx */
char rx_irq_name[IRQ_NAME_SIZE]; /* DEVNAME-qN-rx */
spinlock_t tx_lock;
struct xen_netif_tx_front_ring tx;
int tx_ring_ref;
/*
* {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
* are linked from tx_skb_freelist through skb_entry.link.
*
* NB. Freelist index entries are always going to be less than
* PAGE_OFFSET, whereas pointers to skbs will always be equal or
* greater than PAGE_OFFSET: we use this property to distinguish
* them.
*/
union skb_entry {
struct sk_buff *skb;
unsigned long link;
} tx_skbs[NET_TX_RING_SIZE];
grant_ref_t gref_tx_head;
grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
struct page *grant_tx_page[NET_TX_RING_SIZE];
unsigned tx_skb_freelist;
spinlock_t rx_lock ____cacheline_aligned_in_smp;
struct xen_netif_rx_front_ring rx;
int rx_ring_ref;
struct timer_list rx_refill_timer;
struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
grant_ref_t gref_rx_head;
grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
unsigned long rx_pfn_array[NET_RX_RING_SIZE];
struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
struct mmu_update rx_mmu[NET_RX_RING_SIZE];
};
struct netfront_info {
struct list_head list;
struct net_device *netdev;
struct xenbus_device *xbdev;
/* Multi-queue support */
struct netfront_queue *queues;
/* Statistics */
struct netfront_stats __percpu *stats;
atomic_t rx_gso_checksum_fixup;
};
struct netfront_rx_info {
struct xen_netif_rx_response rx;
struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
};
static void skb_entry_set_link(union skb_entry *list, unsigned short id)
{
list->link = id;
}
static int skb_entry_is_link(const union skb_entry *list)
{
BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
return (unsigned long)list->skb < PAGE_OFFSET;
}
/*
* Access macros for acquiring freeing slots in tx_skbs[].
*/
static void add_id_to_freelist(unsigned *head, union skb_entry *list,
unsigned short id)
{
skb_entry_set_link(&list[id], *head);
*head = id;
}
static unsigned short get_id_from_freelist(unsigned *head,
union skb_entry *list)
{
unsigned int id = *head;
*head = list[id].link;
return id;
}
static int xennet_rxidx(RING_IDX idx)
{
return idx & (NET_RX_RING_SIZE - 1);
}
static struct sk_buff *xennet_get_rx_skb(struct netfront_queue *queue,
RING_IDX ri)
{
int i = xennet_rxidx(ri);
struct sk_buff *skb = queue->rx_skbs[i];
queue->rx_skbs[i] = NULL;
return skb;
}
static grant_ref_t xennet_get_rx_ref(struct netfront_queue *queue,
RING_IDX ri)
{
int i = xennet_rxidx(ri);
grant_ref_t ref = queue->grant_rx_ref[i];
queue->grant_rx_ref[i] = GRANT_INVALID_REF;
return ref;
}
#ifdef CONFIG_SYSFS
static int xennet_sysfs_addif(struct net_device *netdev);
static void xennet_sysfs_delif(struct net_device *netdev);
#else /* !CONFIG_SYSFS */
#define xennet_sysfs_addif(dev) (0)
#define xennet_sysfs_delif(dev) do { } while (0)
#endif
static bool xennet_can_sg(struct net_device *dev)
{
return dev->features & NETIF_F_SG;
}
static void rx_refill_timeout(unsigned long data)
{
struct netfront_queue *queue = (struct netfront_queue *)data;
napi_schedule(&queue->napi);
}
static int netfront_tx_slot_available(struct netfront_queue *queue)
{
return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) <
(NET_TX_RING_SIZE - MAX_SKB_FRAGS - 2);
}
static void xennet_maybe_wake_tx(struct netfront_queue *queue)
{
struct net_device *dev = queue->info->netdev;
struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, queue->id);
if (unlikely(netif_tx_queue_stopped(dev_queue)) &&
netfront_tx_slot_available(queue) &&
likely(netif_running(dev)))
netif_tx_wake_queue(netdev_get_tx_queue(dev, queue->id));
}
static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
{
struct sk_buff *skb;
struct page *page;
skb = __netdev_alloc_skb(queue->info->netdev,
RX_COPY_THRESHOLD + NET_IP_ALIGN,
GFP_ATOMIC | __GFP_NOWARN);
if (unlikely(!skb))
return NULL;
page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
if (!page) {
kfree_skb(skb);
return NULL;
}
skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
/* Align ip header to a 16 bytes boundary */
skb_reserve(skb, NET_IP_ALIGN);
skb->dev = queue->info->netdev;
return skb;
}
static void xennet_alloc_rx_buffers(struct netfron
xen-netfront.rar_remote
版权申诉
164 浏览量
2022-09-23
16:57:10
上传
评论
收藏 14KB RAR 举报
寒泊
- 粉丝: 75
- 资源: 1万+
最新资源
- 基于Golang实现的加权pagerank算法实现.zip
- 基于Java实现的pagerank算法.zip
- 基于C++实现的pagerank算法.zip
- 基于Python实现的pagerank算法.zip
- java面试题-leetcode题解之第14题最长公共前缀.zip
- java面试题-leetcode题解之第28题找出字符串中第一个匹配项的下标.zip
- java面试题-leetcode题解之第31题下一个排列.zip
- java面试题-leetcode题解之第6题Z字形变换.zip
- java面试题-leetcode题解之第8题字符串转换整数atoi.zip
- java面试题-leetcode题解之第13题罗马数字转整数.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈