tso硬件分片是头部拷贝问题

本文详细介绍了e1000网卡驱动中TSO分片机制的具体实现过程,包括如何计算头部偏移量、设置上下文描述符及缓冲区信息等关键步骤,并展示了硬件如何根据这些信息进行数据分片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//skb->date指向了二层头部地址,下面是计算 以太网头 + IP头 大小

static inline int skb_transport_offset(const struct sk_buff *skb)

{
return skb_transport_header(skb) - skb->data;
}

static int e1000_tso(struct e1000_adapter *adapter,

     struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
     __be16 protocol)
{
struct e1000_context_desc *context_desc;
struct e1000_buffer *buffer_info;
unsigned int i;
u32 cmd_length = 0;
u16 ipcse = 0, tucse, mss;
u8 ipcss, ipcso, tucss, tucso, hdr_len;
int err;


if (skb_is_gso(skb)) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
return err;
}


                //hdr_len =  以太网头部  +  IP 头部 + TCP 头部

hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);

                //MSS大小

mss = skb_shinfo(skb)->gso_size;

if (protocol == htons(ETH_P_IP)) {
struct iphdr *iph = ip_hdr(skb);
iph->tot_len = 0;
iph->check = 0;
tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
iph->daddr, 0,
IPPROTO_TCP,
0);
cmd_length = E1000_TXD_CMD_IP;
ipcse = skb_transport_offset(skb) - 1;
} else if (skb_is_gso_v6(skb)) {
ipv6_hdr(skb)->payload_len = 0;
tcp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
0, IPPROTO_TCP, 0);
ipcse = 0;
}
ipcss = skb_network_offset(skb);
ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
tucss = skb_transport_offset(skb);
tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
tucse = 0;


cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
       E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));


i = tx_ring->next_to_use;
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];


context_desc->lower_setup.ip_fields.ipcss  = ipcss;
context_desc->lower_setup.ip_fields.ipcso  = ipcso;
context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
context_desc->upper_setup.tcp_fields.tucss = tucss;
context_desc->upper_setup.tcp_fields.tucso = tucso;

context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);

                //硬件分片使用的分片基础信息

                //网卡硬件分片是需要硬件自动拷贝头部,考多少数据,从哪里开始考?

                //拷贝的是以太网头部数据 + IP头部数据  +  TCP头部(代码流程走到这里已经构建了以太网头部)

                //网卡按照MSS切片数据,也就是纯数据部分为MSS大小

                //所以网卡分片是从以太网头部开始拷贝的

                //但是因为数据部分有变化所以网卡必须同时支持硬件校验

context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);

context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;


context_desc->cmd_and_length = cpu_to_le32(cmd_length);


buffer_info->time_stamp = jiffies;
buffer_info->next_to_watch = i;


if (++i == tx_ring->count) i = 0;
tx_ring->next_to_use = i;


return true;
}
return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值