在测试radius 性能时,想到一个问题,以前tcp报文在ip层处理时,涉及到路由查找,
对于tcp协议报文;skb中没有路由缓存,没有关联的sock;且非分片报文;ip_early_demux设置为true;则调用early_demux函数提前在IP层做established状态的sock查找,并负责将sock结构体成员sk_rx_dst的路由缓存赋值给skb成员_skb_refdst;
TCP入口路由缓存设置时间点如下:
a)作为服务端,三次握手完成时,在函数tcp_v4_syn_recv_sock中创建子sock时赋值;
b)作为客户端在函数tcp_finish_connect;
c)在函数tcp_rcv_established中sock处于established状态时,更新其值--->在tcp_rcv_established函数中已经将输入路由缓存在了sk_rx_dst中,所以early_demux可以通过一次sock查找,同时找到缓存的路由项;
struct sock *tcp_v4_syn_recv_sock() { newsk = tcp_create_openreq_child(sk, req, skb); inet_sk_rx_dst_set(newsk, skb); } void tcp_finish_connect() { //IPv4v6两个回调函数inet_sk_rx_dst_set与inet6_sk_rx_dst_set if (skb) icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); } void tcp_rcv_established() { if (unlikely(!sk->sk_rx_dst)) inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); }
对于UDP协议,对于先查找 对应目标的 sk,先关联skb 和sk,在判断DST_NOCACHE标志,如果成立,增加dst引用计数,设置skb的dst;否则,调用skb_dst_set_noref直接进行设置。
目前radius 主机主要是处理本机到设备之间的udp报文。那是不是可以针对udp 1812 udp1813 做个特殊的定制???
udp_v4_early_demux 处理中提取针对udp 1812 1813的逻辑处理?其余的udp报文就走正常逻辑了!!
int udp_v4_early_demux(struct sk_buff *skb)
{
struct net *net = dev_net(skb->dev);
struct in_device *in_dev = NULL;
const struct iphdr *iph;
const struct udphdr *uh;
struct sock *sk = NULL;
struct dst_entry *dst;
int dif = skb->dev->ifindex;
int sdif = inet_sdif(skb);
int ours;
/* validate the packet */
if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
return 0;
iph = ip_hdr(skb);
uh = udp_hdr(skb);
if (skb->pkt_type == PACKET_MULTICAST) {
in_dev = __in_dev_get_rcu(skb->dev);
if (!in_dev)
return 0;
ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
iph->protocol);
if (!ours)
return 0;
sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
uh->source, iph->saddr,
dif, sdif);
} else if (skb->pkt_type == PACKET_HOST) {
sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,
uh->source, iph->saddr, dif, sdif);
}
if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
return 0;
skb->sk = sk;
skb->destructor = sock_efree;
dst = READ_ONCE(sk->sk_rx_dst);
if (dst)
dst = dst_check(dst, 0);
if (dst) {
u32 itag = 0;
/* set noref for now.
* any place which wants to hold dst has to call
* dst_hold_safe()
*/
skb_dst_set_noref(skb, dst);
/* for unconnected multicast sockets we need to validate
* the source on each packet
*/
if (!inet_sk(sk)->inet_daddr && in_dev)
return ip_mc_validate_source(skb, iph->daddr,
iph->saddr, iph->tos,
skb->dev, in_dev, &itag);
}
return 0;
}
标签:udp,dst,sock,dev,sk,收发,思考,skb,iph From: https://www.cnblogs.com/codestack/p/18224610