skb数据的发送

数据的发送

skb结构和分配

skb分配释放的频率非常高,用kmem_cache分配skb_buf的头部,alloc_skb分配其数据区,alloc_skb最终调用了_kmalloc分配连续物理内存,skb_buf结构体中重要成员:

head指向已分配空间的头部,end指向该空间尾部,data指向有效数据头部,tail指向有效数据尾部,当skb在各层流动时,head和end是不变的。

skb_put:向后移动tail来增加有效数据空间的大小,将skb->tail移动到新的位置 后,老的tail将作为返回值返回;

skb_push:将data前移来增大有效数据空间的大小,将移动后的skb->data返回;

skb_headroom:返回head和data之间的空间大小

skb_tailroom:返回tail和end的空间大小

skb_reserve:将有效数据空间向后移动len,相等于减少了tail空间,拓展了同样大小的head空间

alloc_skb是__alloc_skb的封装,它分配sk_buff结构及数据缓存块:(a)通过kmem_cache_alloc函数从缓存里分配sk_buff数据结构;(b)通过kmalloc分配数据缓冲区。dev_alloc_skb函数主要用于设备驱动中,并在中断上下文中使用。它包装了skb_alloc函数并且在分配空间上多分了16字节空间,当skb数据头需要增加而又长度又小于16字节时,这样就可利用skb_reserve出来的空间,避免了重新分配,由于该函数主要在中断里使用,其在分配空间要求置上原子标志位GFP_ATOMIC。

layer4:传输层(Transport)

tcp_sendmsg##net/ipv4/tcp.c

int tcp_sendmsg(structsock *sk, struct msghdr *msg, size_t size)

Layer 3:网络层(Network Layer)

ip_queue_xmit## net/ipv4/ip_output.c

int ip_queue_xmit(structsock *sk, struct sk_buff *skb, struct flowi *fl)

{

struct inet_sock *inet = inet_sk(sk);

struct net *net = sock_net(sk);

struct ip_options_rcu *inet_opt;

struct flowi4 *fl4;

struct rtable *rt;

struct iphdr *iph;

int res;

rt = skb_rtable(skb);

if (rt)

            goto packet_routed;如果已经路由

/* Make sure we can route this packet.*/

rt = (struct rtable*)__sk_dst_check(sk, 0);如果没被路由

   if (!rt){      

/* If this fails, retransmitmechanism of transport layer will

* keep trying until routeappears or the connection times

* itself out.

*/

rt = ip_route_output_ports(net,fl4, sk,

daddr, inet->inet_saddr,

  inet->inet_dport,

inet->inet_sport,

sk->sk_protocol,

RT_CONN_FLAGS(sk),

sk->sk_bound_dev_if);

}

res = ip_local_out(net, sk, skb); //触使包发到数据链路层

}

在分配路由表的时候关联netdev

ip_route_output_ports

---> ip_route_output_flow

--->__ip_route_output_key

--->__ip_route_output_key_hash

--->__mkroute_output

--->rt_dst_alloc

struct rtable*__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,

intmp_hash)

{

struct net_device *dev_out = NULL;

dev_out = dev_get_by_index_rcu(net,fl4->flowi4_oif);

rth = __mkroute_output(&res, fl4, orig_oif,dev_out, flags);

}

net/ipv4/route.c

static struct rtable*rt_dst_alloc(struct net_device *dev,

unsigned intflags, u16 type,

boolnopolicy, bool noxfrm, bool will_cache)

{

struct rtable *rt;

rt = dst_alloc(&ipv4_dst_ops, dev,1, DST_OBSOLETE_FORCE_CHK,

(will_cache ? 0 :(DST_HOST | DST_NOCACHE)) |

(nopolicy ? DST_NOPOLICY: 0) |

(noxfrm ? DST_NOXFRM :0));

if (rt) {

rt->rt_genid =rt_genid_ipv4(dev_net(dev));

rt->rt_flags = flags;

rt->rt_type = type;

rt->rt_is_input = 0;

rt->rt_iif = 0;

   rt->rt_pmtu = 0;

rt->rt_gateway = 0;

rt->rt_uses_gateway = 0;

rt->rt_table_id = 0;

INIT_LIST_HEAD(&rt->rt_uncached);

     rt->dst.output = ip_output;

if (flags & RTCF_LOCAL)

rt->dst.input =ip_local_deliver;

}

return rt;

}

int ip_local_out(structnet *net, struct sock *sk, struct sk_buff *skb)

{      

int err;

err = __ip_local_out(net, sk, skb);

if (likely(err == 1))

 err = dst_output(net, sk, skb);

return err;

}

/* Output packet tonetwork from transport. */

static inline intdst_output(struct net *net, struct sock *sk, struct sk_buff *skb)

{

return skb_dst(skb)->output(net, sk,skb);调用rt_dst_alloc中的ip_output

}

/*ip_output单播包,ip_mc_output组播包*/

int ip_output(struct net*net, struct sock *sk, struct sk_buff *skb)

{      

struct net_device *dev =skb_dst(skb)->dev;    

IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT,skb->len);

     skb->dev = dev;

skb->protocol =htons(ETH_P_IP);  

return NF_HOOK_COND(NFPROTO_IPV4,NF_INET_POST_ROUTING,

net, sk, skb, NULL,dev,

ip_finish_output,

!(IPCB(skb)->flags& IPSKB_REROUTED));

}

ip_output会调用netfilter的钩子函数

ip_finish_output

--->ip_finish_output2

---->dst->neighbour->output

在IPv4中,neighbour subsystem使用的是arp,所以一般情况下,dst->neighbour->outpu指向的是arp_generic_ops->neigh_resolve_output。

neigh_resolve_output

---->dev_queue_xmit###net/core/dev.c

---->dev_hard_start_xmit

----> ndo_start_xmit

/* dev_queue_xmit是对skb做些最后的处理并且第一次尝试发送,软中断是将前者发送失败或者没发完的包发送出去*/

数据链路层

在驱动中实现ndo_start_xmit函数

static structnet_device_ops xxx_netdev_ops = {

.ndo_init = xxx_init,

.ndo_uninit = xxx_uninit,

.ndo_open = xxx_open,

.ndo_stop = xxx_close,

.ndo_start_xmit = xxx_start_xmit,

.ndo_get_stats = xxx_get_stats,

.ndo_tx_timeout = xxx_tx_timeout,

.ndo_do_ioctl = xxx_ioctl,

};

网络子系统部分实现一个传输队列qdisc,系统中每个CPU都拥有自己的传输独立,每个要发送到数据包都先放到传输队列中,驱动调用ndo_start_xmit将包发到硬件缓存后,当网络子系统有新的包需要发送时,可能会再次调用ndo_start_xmit,但这是硬件可能还没有来得及将包发出,因此这时需要内核子系统维护一个发送队列。当驱动感知到硬件无法再接收更多数据时,netif_stop_queue通知内核网络子系统停止包的发送,当可以继续传输数据时用netif_wake_queue触发继续发送,netif_start_queue用在驱动最初简单地设置发送标志,另外当连接状态有变时,需要告知内核子系统:

netif_carrier_on

作用告诉内核子系统网络链接完整。

netif_carrier_off

作用告诉内核子系统网络断开。

netif_carrier_ok

作用:查询网络断开还是链接。

以上函数主要是改变net_device dev的state状态来告知内核链路状态的变化,网络设备将数据包发送完成之后,将向主机产生一个硬件中断,此后需要释放skb等系列后续操作

reference:

socket数据发送过程zz

Socket层实现系列— send()类发送函数的实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: skb recycle是指射频技术中的信道回收技术,主要用于无线通信系统中的信号处理和网络优化。在无线通信系统中,信道回收技术能够提高系统的频谱效率和用户的数据传输速率。 skb recycle的原理是通过对已经传输的信号进行回收和重新利用,以提高频谱利用率。具体而言,它能够捕获已经传输过的信号,对这些信号进行补偿和修正,然后再次发送给其他需要使用该信号的用户。因此,信道回收技术能够显著减少频谱资源的浪费,并且在减少信号干扰的同时提高了系统的容量。 skb recycle技术在无线通信系统中的应用广泛。例如,在蜂窝网络中,当用户在移动中切换到新的基站时,之前所使用的频率资源可以被回收利用。此外,信道回收技术还可以被应用于多天线系统中,通过捕获和再利用多径信号,提高系统的容量和覆盖范围。 总之,skb recycle是一种利用信道回收技术提高无线通信系统频谱效率和用户数据传输速率的方法。它可以帮助无线通信系统更高效地利用频谱资源,提升用户体验和网络性能。 ### 回答2: skb recycle是指对skb(Socket Buffer)进行回收利用的过程。 在操作系统中,skb是一种用于在内核与网络协议栈之间传输数据数据结构。它包含有关数据包的各种信息,例如发送方和接收方的IP地址、协议类型、数据长度等。 skb recycle是一种优化技术,旨在提高网络数据传输的效率和性能。在传输数据时,操作系统会创建多个skb对象,用于存储不同的数据包。一旦数据包传输完成后,这些被使用过的skb对象就可以进行回收利用,以避免频繁地创建和销毁对象,从而减少系统开销。 skb recycle的核心思想是在创建skb对象时,使用一个空闲列表来记录可用的回收对象。当需要新的skb对象时,首先从空闲列表中获取,如果列表为空,则会创建新的对象。而当数据包完成传输后,就将该skb对象重新加入到空闲列表中,以供下一次使用。 通过使用skb recycle技术,可以显著提高网络性能和吞吐量。因为减少了频繁地创建和销毁对象,系统的开销大大降低。同时,有效地回收利用已用过的skb对象,也减少了内存资源的浪费。 总之,skb recycle是一种对skb对象进行回收利用的技术,可以提高网络数据传输的效率和性能,减少系统开销和内存浪费。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值