Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send packet and local-net #4

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions linux-6.2/arch/x86/include/asm/current.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

struct task_struct;

//存储该 CPU 核心的一些运行时信息
struct pcpu_hot {
union {
struct {
Expand All @@ -22,6 +23,7 @@ struct pcpu_hot {
#endif
unsigned long top_of_stack;
void *hardirq_stack_ptr;
//存储软中断状态
u16 softirq_pending;
#ifdef CONFIG_X86_64
bool hardirq_stack_inuse;
Expand Down
1 change: 1 addition & 0 deletions linux-6.2/arch/x86/include/asm/hardirq.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ extern u64 arch_irq_stat_cpu(unsigned int cpu);
extern u64 arch_irq_stat(void);
#define arch_irq_stat arch_irq_stat

//x86 用于存储当前CPU的软中断(softirq)状态。
#define local_softirq_pending_ref pcpu_hot.softirq_pending

#if IS_ENABLED(CONFIG_KVM_INTEL)
Expand Down
25 changes: 21 additions & 4 deletions linux-6.2/drivers/net/ethernet/intel/igb/igb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,8 +1226,8 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
memset(q_vector, 0, size);
}
if (!q_vector)
return -ENOMEM;

return -ENOMEM;
/* initialize NAPI */
//使用 netif_napi_add 注册 NAPI,并指定 igb_poll 作为网络中断的处理函数。NAPI 是一种机制,用于减少中断频率并提高网络吞吐量。
netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll);
Expand Down Expand Up @@ -2165,6 +2165,7 @@ int igb_up(struct igb_adapter *adapter)
wr32(E1000_CTRL_EXT, reg_data);
}

//启用网卡
netif_tx_start_all_queues(adapter->netdev);

/* start the watchdog. */
Expand Down Expand Up @@ -4258,6 +4259,7 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
struct device *dev = tx_ring->dev;
int size;

//申请igb_tx_buffer数组
size = sizeof(struct igb_tx_buffer) * tx_ring->count;

tx_ring->tx_buffer_info = vmalloc(size);
Expand Down Expand Up @@ -6177,6 +6179,7 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
return __igb_maybe_stop_tx(tx_ring, size);
}

//将数据放入缓冲区
static int igb_tx_map(struct igb_ring *tx_ring,
struct igb_tx_buffer *first,
const u8 hdr_len)
Expand All @@ -6191,17 +6194,22 @@ static int igb_tx_map(struct igb_ring *tx_ring,
u32 cmd_type = igb_tx_cmd_type(skb, tx_flags);
u16 i = tx_ring->next_to_use;

//获取发送描述符
tx_desc = IGB_TX_DESC(tx_ring, i);

igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len);

//计算头部和数据长度
size = skb_headlen(skb);
data_len = skb->data_len;

//将数据映射到 DMA 地址
dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);

tx_buffer = first;


//负责处理包含多个片段的 TCP/UDP 数据包 遍历数据包 skb 的所有片段
for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
if (dma_mapping_error(tx_ring->dev, dma))
goto dma_error;
Expand Down Expand Up @@ -6245,14 +6253,15 @@ static int igb_tx_map(struct igb_ring *tx_ring,

size = skb_frag_size(frag);
data_len -= size;

//将当前片段映射到设备的 DMA 地址
dma = skb_frag_dma_map(tx_ring->dev, frag, 0,
size, DMA_TO_DEVICE);

tx_buffer = &tx_ring->tx_buffer_info[i];
}

/* write last descriptor with RS and EOP bits */
//设置最后一个描述符
cmd_type |= size | IGB_TXD_DCMD;
tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);

Expand Down Expand Up @@ -6430,6 +6439,7 @@ int igb_xmit_xdp_ring(struct igb_adapter *adapter,
return IGB_XDP_CONSUMED;
}

//igb网卡发送数据
netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
struct igb_ring *tx_ring)
{
Expand Down Expand Up @@ -6457,12 +6467,14 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
}

/* record the location of the first descriptor for this packet */
//记录第一个描述符的位置
first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
first->type = IGB_TYPE_SKB;
first->skb = skb;
first->bytecount = skb->len;
first->gso_segs = 1;

//时间戳
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);

Expand All @@ -6481,6 +6493,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
}
}

//vlan
if (skb_vlan_tag_present(skb)) {
tx_flags |= IGB_TX_FLAGS_VLAN;
tx_flags |= (skb_vlan_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);
Expand All @@ -6496,6 +6509,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
else if (!tso)
igb_tx_csum(tx_ring, first);

//调用 igb_tx_map 函数将数据包映射到硬件发送环的描述符
if (igb_tx_map(tx_ring, first, hdr_len))
goto cleanup_tx_tstamp;

Expand Down Expand Up @@ -6529,6 +6543,7 @@ static inline struct igb_ring *igb_tx_queue_mapping(struct igb_adapter *adapter,
return adapter->tx_ring[r_idx];
}

//igb网卡发送
static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
struct net_device *netdev)
{
Expand Down Expand Up @@ -8884,6 +8899,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
#if (PAGE_SIZE < 8192)
frame_sz = igb_rx_frame_truesize(rx_ring, 0);
#endif
//初始化和准备 XDP 缓冲区
xdp_init_buff(&xdp, frame_sz, &rx_ring->xdp_rxq);

//在一个循环中,处理接收队列中的数据包。每次迭代最多处理 budget 个数据包,直到达到 budget
Expand Down Expand Up @@ -8918,6 +8934,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
//获取缓冲区的地址
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;

//处理时间戳
/* pull rx packet timestamp if available and valid */
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
int ts_hdr_len;
Expand Down Expand Up @@ -8970,7 +8987,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
rx_buffer->pagecnt_bias++;
break;
}

//释放接收缓冲区
igb_put_rx_buffer(rx_ring, rx_buffer, rx_buf_pgcnt);
cleaned_count++;

Expand Down
3 changes: 3 additions & 0 deletions linux-6.2/drivers/net/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ EXPORT_SYMBOL(blackhole_netdev);
/* The higher levels take care of making this non-reentrant (it's
* called with bh's disabled).
*/
//本机网络io的发送
static netdev_tx_t loopback_xmit(struct sk_buff *skb,
struct net_device *dev)
{
Expand All @@ -76,6 +77,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
/* do not fool net_timestamp_check() with various clock bases */
skb_clear_tstamp(skb);

//剥离和源socket的联系
skb_orphan(skb);

/* Before queueing this packet to __netif_rx(),
Expand All @@ -86,6 +88,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
skb->protocol = eth_type_trans(skb, dev);

len = skb->len;
//调用__netif_rx
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
dev_lstats_add(dev, len);

Expand Down
1 change: 1 addition & 0 deletions linux-6.2/include/linux/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ extern bool initcall_debug;
*
* Only for built-in code, not modules.
*/
//在SMP初始化前执行
#define early_initcall(fn) __define_initcall(fn, early)

/*
Expand Down
1 change: 1 addition & 0 deletions linux-6.2/include/linux/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ DECLARE_STATIC_KEY_FALSE(force_irqthreads_key);

#ifndef local_softirq_pending

//相应架构没有定义时
#ifndef local_softirq_pending_ref
//local_softirq_pending_ref实际上是irq_stat结构中的__softirq_pending,__softirq_pending字段中的每一个bit,对应着某一个软中断,某个bit被置位,说明有相应的软中断等待处理。
#define local_softirq_pending_ref irq_stat.__softirq_pending
Expand Down
7 changes: 5 additions & 2 deletions linux-6.2/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -3037,6 +3037,7 @@ u16 dev_pick_tx_cpu_id(struct net_device *dev, struct sk_buff *skb,
int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev);
int __dev_direct_xmit(struct sk_buff *skb, u16 queue_id);

//设备子系统入口函数
static inline int dev_queue_xmit(struct sk_buff *skb)
{
return __dev_queue_xmit(skb, NULL);
Expand Down Expand Up @@ -4867,7 +4868,7 @@ static inline ktime_t netdev_get_tstamp(struct net_device *dev,

return hwtstamps->hwtstamp;
}

//网络设备子系统 发送
static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,
struct sk_buff *skb, struct net_device *dev,
bool more)
Expand All @@ -4881,13 +4882,15 @@ static inline bool netdev_xmit_more(void)
return __this_cpu_read(softnet_data.xmit.more);
}

//发送数据包
static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq, bool more)
{
const struct net_device_ops *ops = dev->netdev_ops;
netdev_tx_t rc;

//调用
rc = __netdev_start_xmit(ops, skb, dev, more);
//更新时间戳
if (rc == NETDEV_TX_OK)
txq_trans_update(txq);

Expand Down
2 changes: 2 additions & 0 deletions linux-6.2/include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -2095,10 +2095,12 @@ static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
* The reference count is not incremented and the reference is therefore
* volatile. Use with caution.
*/
//获取sk_buff_head队列的尾部元素
static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)
{
struct sk_buff *skb = READ_ONCE(list_->prev);

//skb为自己 即队列为空
if (skb == (struct sk_buff *)list_)
skb = NULL;
return skb;
Expand Down
9 changes: 6 additions & 3 deletions linux-6.2/include/linux/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ typedef __kernel_sa_family_t sa_family_t;
/*
* 1003.1g requires sa_family_t and that sa_data is char.
*/

//对端地址
struct sockaddr {
//地址族
sa_family_t sa_family; /* address family, AF_xxx */
//地址数据
union {
char sa_data_min[14]; /* Minimum 14 bytes of protocol address */
DECLARE_FLEX_ARRAY(char, sa_data);
Expand All @@ -51,13 +53,14 @@ struct linger {
* system, not 4.3. Thus msg_accrights(len) are now missing. They
* belong in an obscure libc emulation or the bin.
*/

//消息结构体
struct msghdr {
void *msg_name; /* ptr to socket address structure */
int msg_namelen; /* size of socket address structure */

int msg_inq; /* output, data left in socket */

//数据信息
struct iov_iter msg_iter; /* data */

/*
Expand Down Expand Up @@ -166,7 +169,7 @@ static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr
{
return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg);
}

//获取数据长度
static inline size_t msg_data_left(struct msghdr *msg)
{
return iov_iter_count(&msg->msg_iter);
Expand Down
6 changes: 5 additions & 1 deletion linux-6.2/include/linux/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
return raw_copy_to_user(to, from, n);
}

//
#ifdef INLINE_COPY_FROM_USER
static inline __must_check unsigned long
_copy_from_user(void *to, const void __user *from, unsigned long n)
Expand All @@ -124,6 +125,7 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
might_fault();
if (!should_fail_usercopy() && likely(access_ok(from, n))) {
instrument_copy_from_user_before(to, from, n);
//实际操作
res = raw_copy_from_user(to, from, n);
instrument_copy_from_user_after(to, from, n, res);
}
Expand Down Expand Up @@ -154,9 +156,11 @@ extern __must_check unsigned long
_copy_to_user(void __user *, const void *, unsigned long);
#endif

//从用户空间拷贝
static __always_inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
{
//检查to的空间
if (check_copy_size(to, n, false))
n = _copy_from_user(to, from, n);
return n;
Expand Down
2 changes: 2 additions & 0 deletions linux-6.2/include/linux/uio.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct iov_iter_state {
unsigned long nr_segs;
};

//数据信息
struct iov_iter {
u8 iter_type;
bool nofault;
Expand All @@ -49,6 +50,7 @@ struct iov_iter {
};
size_t count;
union {
//实际数据
const struct iovec *iov;
const struct kvec *kvec;
const struct bio_vec *bvec;
Expand Down
1 change: 1 addition & 0 deletions linux-6.2/include/linux/wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ extern void add_wait_queue_exclusive(struct wait_queue_head *wq_head, struct wai
extern void add_wait_queue_priority(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
extern void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);

//将wq_entry放入wq_head
static inline void __add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry)
{
struct list_head *head = &wq_head->head;
Expand Down
1 change: 1 addition & 0 deletions linux-6.2/include/net/dst.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ INDIRECT_CALLABLE_DECLARE(int ip6_output(struct net *, struct sock *,
INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *,
struct sk_buff *));
/* Output packet to network from transport. */
//出口函数 回调ip_output
static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return INDIRECT_CALL_INET(skb_dst(skb)->output,
Expand Down
2 changes: 2 additions & 0 deletions linux-6.2/include/net/ip_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ static inline struct fib_table *fib_new_table(struct net *net, u32 id)
return fib_get_table(net, id);
}

//查找路由核心函数
static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
struct fib_result *res, unsigned int flags)
{
Expand All @@ -314,6 +315,7 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,

rcu_read_lock();

//查询main路由表
tb = fib_get_table(net, RT_TABLE_MAIN);
if (tb)
err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);
Expand Down
Loading