Skip to content

Commit

Permalink
send packet and local-net
Browse files Browse the repository at this point in the history
  • Loading branch information
张铭轩 committed Mar 7, 2025
1 parent 215d2ba commit 733a0e5
Show file tree
Hide file tree
Showing 37 changed files with 352 additions and 66 deletions.
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

0 comments on commit 733a0e5

Please sign in to comment.