• 美国发起贸易战,我们要让世界知道美元、美债并不可靠 2019-06-05
  • 紫光阁中共中央国家机关工作委员会 2019-05-31
  • 监察体制改革后 湘西半年72名公职人员主动交代问题 2019-05-12
  • 媒体宣传报道重庆日报 王国平:扮靓重庆两江四岸” 让城市有机更新 2019-04-26
  • 我相信“交警雨中护送高考生”是真,“交警雨中护送高考生”反被该高考生家长投诉是假。 2019-04-16
  • 14名消防员日巡逻28公里 洗冷水澡 2019-04-10
  • 靶壕有了“蓝军”,百发百中的“神枪手”练起来 2019-04-10
  • 不是秀强大了,别人就会来做朋友,这逻辑不对 2019-04-01
  • 候选企业:中国石油呼和浩特石化公司 2019-03-26
  • 航天员沙漠野外生存训练完美收官!为第一天团打call 2019-03-25
  • 请问,建立市场经济后,原计划经济哪里去?改革后,我们还在实行计划经济,为何没有提及? 2019-03-25
  • 构建年轻干部梯次培养链 2019-03-19
  • 孙实的专栏作者中国国家地理网 2019-03-15
  • 湖南师范大学举行研究阐释党的十九大精神国家社科基金重大专项学术研讨会 2019-03-15
  • [雷人]蠢货!土地处于不同的城市和地段,关联的资源不一样,价值也不一样。不然给咱俩同样面积的土地,咱的在北上广深,你的在边远山区,你干么? 2019-03-08
  • 频道栏目
    神奇公式秒杀全国11选5 > 网络 > 路由器 > 正文
    SKB路由缓存与SOCK路由缓存交互知识讲解
    2018-05-10 10:07:08         来源:redwings的博客  
    收藏   我要投稿

    神奇公式秒杀全国11选5 www.2zfa.com skb结构体中的成员_skb_refdst与sock结构体中成员sk_rx_dst(缓存入口路由)和sk_dst_cache(缓存出口路由)成员之间的交互操作。

    SOCK入口路由与SKB路由缓存

    内核在接收流程中,调用early_demux函数提前在IP层做established状态的sock查找,并负责将sock结构体成员sk_rx_dst的路由缓存赋值给skb成员_skb_refdst,对于UDP协议,先判断DST_NOCACHE标志,如果成立,增加dst引用计数,设置skb的dst;否则,调用skb_dst_set_noref直接进行设置。

    void udp_v4_early_demux(struct sk_buff *skb)
    {
        dst = READ_ONCE(sk->sk_rx_dst);
    
        if (dst)
            dst = dst_check(dst, 0);
        if (dst) {
            /* DST_NOCACHE can not be used without taking a reference */
            if (dst->flags & DST_NOCACHE) {
                if (likely(atomic_inc_not_zero(&dst->__refcnt)))
                    skb_dst_set(skb, dst);
            } else {
                skb_dst_set_noref(skb, dst);
            }
        }
    }

    对于TCP协议,直接调用skb_dst_set_noref函数,将sock结构体成员sk_rx_dst缓存到skb结构体中。

    void tcp_v4_early_demux(struct sk_buff *skb)
    {
        if (sk->sk_state != TCP_TIME_WAIT) {
            struct dst_entry *dst = sk->sk_rx_dst;
    
            if (dst)
                dst = dst_check(dst, 0);
            if (dst &&
                inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
                skb_dst_set_noref(skb, dst);
        }
    }

    同样都为early_demux函数,都是从sk->sk_rx_dst获取路由缓存,tcp和udp的存在明显差别。TCP直接赋值,UDP需要先判断DST_NOCACHE标志。此情况是由UDP与TCP在sock中缓存dst时的处理不同造成的,TCP预先调用了dst_hold_safe函数,进行了DST_NOCACHE标志的判断处理,如未缓存则增加了引用计数。然而,UDP在缓存路由dst时,使用xchg函数,未判断也未增加引用计数,所以需要在后续判断处理。

    static inline bool dst_hold_safe(struct dst_entry *dst)
    {
        if (dst->flags & DST_NOCACHE)
            return atomic_inc_not_zero(&dst->__refcnt);
        dst_hold(dst);
    }
    
    void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
    {
        struct dst_entry *dst = skb_dst(skb);
    
        if (dst && dst_hold_safe(dst)) {
            sk->sk_rx_dst = dst;
            inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
        }
    }
    
    static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
    {
        struct dst_entry *old;
    
        dst_hold(dst);
        old = xchg(&sk->sk_rx_dst, dst);
        dst_release(old);
    }


    SOCK出口路由与SKB路由缓存

    对于UDP协议客户端,其在connect时(UDP客户端connect不同于TCP,仅绑定通信端地址),查询路由,缓存到sock结构体的sk_dst_cache中。

    int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
    {
        rt = ip_route_connect(...);
        sk_dst_set(sk, &rt->dst);
    }
    之后,发送UDP数据包时,检查sock结构体中的出口路由是否有效,有效的话可不用再次查询路由表,在函数ip_make_skb中直接使用rt,并且调用skb_dst_set赋值给skb的_skb_refdst结构体,以便在发送过程中使用。

    对于UDP服务端,在首次发包检测到rt为空时,查询路由表得到出口路由,缓存在sock结构中,之后发包时rt有效,省去再次查询。

    struct sk_buff *__ip_make_skb(...)
    {
        skb_dst_set(skb, &rt->dst);
    }
    
    int udp_sendmsg(...)
    {
        if (connected)
            rt = (struct rtable *)sk_dst_check(sk, 0);
        if (rt == NULL) {
            rt = ip_route_output_flow(net, fl4, sk);
            if (connected)
                sk_dst_set(sk, dst_clone(&rt->dst));
        }
    
        skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen,
                sizeof(struct udphdr), &ipc, &rt,
                msg->msg_flags);
    }

    IP层发送数据包时(调用ip_queue_xmit),检测sock结构中出口路由缓存,如果有效,设置到skb结构体中。否则重新进行出口路由查找。

    int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
    {
        rt = (struct rtable *)__sk_dst_check(sk, 0);
        if (rt == NULL) {
            rt = ip_route_output_ports(...);
            sk_setup_caps(sk, &rt->dst);
        }
        skb_dst_set_noref(skb, &rt->dst);
    }

    内核版本

    linux-3.10.0

    点击复制链接 与好友分享!回本站首页
    上一篇:在家中同时安装两个无线路由器的设置方法
    下一篇:openwrt做二级路由时发生错误,怎么回事?
    相关文章
    图文推荐
    点击排行

    关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 神奇公式秒杀全国11选5

    版权所有: 神奇公式秒杀全国11选5--致力于做实用的IT技术学习网站

  • 美国发起贸易战,我们要让世界知道美元、美债并不可靠 2019-06-05
  • 紫光阁中共中央国家机关工作委员会 2019-05-31
  • 监察体制改革后 湘西半年72名公职人员主动交代问题 2019-05-12
  • 媒体宣传报道重庆日报 王国平:扮靓重庆两江四岸” 让城市有机更新 2019-04-26
  • 我相信“交警雨中护送高考生”是真,“交警雨中护送高考生”反被该高考生家长投诉是假。 2019-04-16
  • 14名消防员日巡逻28公里 洗冷水澡 2019-04-10
  • 靶壕有了“蓝军”,百发百中的“神枪手”练起来 2019-04-10
  • 不是秀强大了,别人就会来做朋友,这逻辑不对 2019-04-01
  • 候选企业:中国石油呼和浩特石化公司 2019-03-26
  • 航天员沙漠野外生存训练完美收官!为第一天团打call 2019-03-25
  • 请问,建立市场经济后,原计划经济哪里去?改革后,我们还在实行计划经济,为何没有提及? 2019-03-25
  • 构建年轻干部梯次培养链 2019-03-19
  • 孙实的专栏作者中国国家地理网 2019-03-15
  • 湖南师范大学举行研究阐释党的十九大精神国家社科基金重大专项学术研讨会 2019-03-15
  • [雷人]蠢货!土地处于不同的城市和地段,关联的资源不一样,价值也不一样。不然给咱俩同样面积的土地,咱的在北上广深,你的在边远山区,你干么? 2019-03-08