当前位置:   article > 正文

内核网络协议栈传输层协议框架_传输层预分流功能的作用

传输层预分流功能的作用

 

Linux内核支持的传输层协议包括传统的TCP,UDP,以及IPIP、GRE等隧道协议。内核协议栈使用net_protocol结构体表示其所支持的传输层协议,系统初始化或者相应协议模块加载时,具体的协议将根据协议号将其实现的net_protocol结构体注册到协议栈中,即以协议号为索引添加到全局结构体指针数组inet_protos[]中。inet_protos数据大小为MAX_INET_PROTOS(256),由于IP头部中protocol字段为8bit位,256以足够保存所有协议。

  1. struct net_protocol {
  2. int (*early_demux)(struct sk_buff *skb);
  3. int (*early_demux_handler)(struct sk_buff *skb);
  4. int (*handler)(struct sk_buff *skb);
  5. void (*err_handler)(struct sk_buff *skb, u32 info);
  6. unsigned int no_policy:1,
  7. netns_ok:1,
  8. icmp_strict_tag_validation:1;
  9. };
  10. struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;

传输层的预分流功能(early_demux/early_demux_handler)目前只有TCP和UDP协议有实现,其它类型不支持。handler回调函数为协议的核心处理函数。内核提供inet_add_protocol函数向系统注册协议处理结构。

传输层协议

目前Linux内核协议栈支持的协议有以下,分成3个组列出:

标准传输协议:

  1. -------------------------------------------------------------------------------
  2. | 协议号 | 协议栈注册结构 | 处理函数(handler) |
  3. -------------------------------------------------------------------------------
  4. | IPPROTO_UDP(17) | udp_protocol | udp_rcv |
  5. | IPPROTO_TCP(6) | tcp_protocol | tcp_v4_rcv |
  6. | IPPROTO_ICMP(1) | icmp_protocol | icmp_rcv |
  7. | IPPROTO_IGMP(2) | igmp_protocol | igmp_rcv |
  8. | IPPROTO_DCCP(33) | dccp_v4_protocol | dccp_v4_rcv |
  9. | IPPROTO_SCTP(132) | sctp_protocol | sctp_rcv |
  10. | IPPROTO_UDPLITE(136) | udplite_protocol | udplite_rcv |
  11. | IPPROTO_PIM(103) | pim_protocol | pim_rcv |
  12. -------------------------------------------------------------------------------

隧道相关协议:

  1. -------------------------------------------------------------------------------
  2. | IPPROTO_L2TP(115) | l2tp_ip_protocol | l2tp_ip_recv |
  3. | IPPROTO_IPIP(4) | tunnel4_protocol | tunnel4_rcv |
  4. | IPPROTO_IPV6(41) | tunnel64_protocol | tunnel64_rcv |
  5. | IPPROTO_MPLS(137) | tunnelmpls4_protocol | tunnelmpls4_rcv |
  6. | IPPROTO_GRE(47) | net_gre_protocol | gre_rcv |
  7. -------------------------------------------------------------------------------

IPSec相关协议:

  1. -------------------------------------------------------------------------------
  2. | IPPROTO_AH(51) | ah4_protocol | xfrm4_ah_rcv |
  3. | IPPROTO_ESP(50) | esp4_protocol | xfrm4_esp_rcv |
  4. | IPPROTO_COMP(108) | ipcomp4_protocol | xfrm4_ipcomp_rcv |
  5. -------------------------------------------------------------------------------

对于IPv6与以上IPv4结构相同。内核协议栈使用inet6_protocol结构体表示其所支持的传输层协议,使用inet6_add_protocol向内核注册协议。

  1. struct inet6_protocol {
  2. void (*early_demux)(struct sk_buff *skb);
  3. void (*early_demux_handler)(struct sk_buff *skb);
  4. int (*handler)(struct sk_buff *skb);
  5. void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info);
  6. unsigned int flags; /* INET6_PROTO_xxx */
  7. };

目前内核支持的IPv6传输层协议:

  1. -------------------------------------------------------------------------------
  2. | 协议号 | 协议栈注册结构 | 处理函数(handler) |
  3. -------------------------------------------------------------------------------
  4. | IPPROTO_SCTP | sctpv6_protocol | sctp6_rcv |
  5. | IPPROTO_UDPLITE | udplitev6_protocol | udplitev6_rcv |
  6. | IPPROTO_UDP | udpv6_protocol | udpv6_rcv |
  7. | IPPROTO_FRAGMENT | frag_protocol | ipv6_frag_rcv |
  8. | IPPROTO_ROUTING | rthdr_protocol | ipv6_rthdr_rcv |
  9. | IPPROTO_DSTOPTS | destopt_protocol | ipv6_destopt_rcv |
  10. | IPPROTO_NONE | nodata_protocol | dst_discard |
  11. | IPPROTO_TCP | tcpv6_protocol | tcp_v6_rcv |
  12. | IPPROTO_PIM | pim6_protocol | pim6_rcv |
  13. | IPPROTO_ICMPV6 | icmpv6_protocol | icmpv6_rcv |
  14. | IPPROTO_DCCP | dccp_v6_protocol | dccp_v6_rcv |
  15. -------------------------------------------------------------------------------

隧道相关协议:

  1. -------------------------------------------------------------------------------
  2. | IPPROTO_L2TP | l2tp_ip6_protocol | l2tp_ip6_recv |
  3. | IPPROTO_IPV6 | tunnel6_protocol | tunnel6_rcv |
  4. | IPPROTO_IPIP | tunnel46_protocol | tunnel46_rcv |
  5. | IPPROTO_GRE | ip6gre_protocol | gre_rcv |
  6. -------------------------------------------------------------------------------

IPSec相关协议:

  1. -------------------------------------------------------------------------------
  2. | IPPROTO_AH(51) | ah4_protocol | xfrm6_ah_rcv |
  3. | IPPROTO_ESP(50) | esp4_protocol | xfrm6_esp_rcv |
  4. | IPPROTO_COMP(108) | ipcomp4_protocol | xfrm6_ipcomp_rcv |
  5. -------------------------------------------------------------------------------

协议处理

网络层函数ip_local_deliver_finish(IPv6:ip6_input_finish)负责调用上层传输协议回调函数。如下代码所示,从IP头部取出protocol协议号字段,以此为所以到inet_protos(IPv6:inet6_protos)数组中取出相应的注册协议结构体,调用其中的回调函数(handler)。

  1. static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
  2. {
  3. int protocol = ip_hdr(skb)->protocol;
  4. const struct net_protocol *ipprot;
  5. ipprot = rcu_dereference(inet_protos[protocol]);
  6. if (ipprot)
  7. ret = ipprot->handler(skb);
  8. }

如果接收到ICMP错误信息,根据协议类型ICMP模块调用相应的协议错误处理函数(err_handler):

  1. static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
  2. {
  3. const struct net_protocol *ipprot;
  4. int protocol = iph->protocol;
  5. (...)
  6. ipprot = rcu_dereference(inet_protos[protocol]);
  7. if (ipprot && ipprot->err_handler)
  8. ipprot->err_handler(skb, info);
  9. }

预分流功能

预分流时网络层在处理接收到数据包时,在路由查找和netfilter的hook点NF_INET_LOCAL_IN之前,提前查找套接口,取得套接口中缓存路由项的功能。这样省去了之后的路由查找,此功能仅适用处于established状态的套接口。但是对于要转发的报文,增加了不必要的套接口查找操作。

在ip_rcv_finish函数中,根据协议号找到相应的协议处理结构,调用其中的early_demux回调函数。early_demux成员变量指向同结构中的early_demux_handler,用户可单独关闭TCP或者UDP的预分流,关闭时其early_demux指向空指针。用户可通过proc文件(/proc/sys/net/ipv4/ip_early_demux)整个关闭预分流功能。

  1. static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
  2. {
  3. const struct iphdr *iph = ip_hdr(skb);
  4. int (*edemux)(struct sk_buff *skb);
  5. struct net_device *dev = skb->dev;
  6. if (net->ipv4.sysctl_ip_early_demux &&
  7. !skb_dst(skb) &&
  8. !skb->sk &&
  9. !ip_is_fragment(iph)) {
  10. const struct net_protocol *ipprot;
  11. int protocol = iph->protocol;
  12. ipprot = rcu_dereference(inet_protos[protocol]);
  13. if (ipprot && (edemux = READ_ONCE(ipprot->early_demux)))
  14. err = edemux(skb);
  15. }
  16. }

IPSec传输协议

关于IPSec的协议注册需要注意,内核子模块XFRM首先注册了通用的net_protocol结构和三个协议的回调函数(xfrm4_ah_rcv/xfrm4_esp_rcv/xfrm4_ipcomp_rcv)。但是这三个回调实际上不进行实际的报文处理,而是作为入口,根据注册的子协议结构,调用XFRM系统自身的子协议处理函数。例如对于ESP协议,XFRM模块注册了两个子协议结构esp4_protocol和vti_esp4_protocol,分别对应两个处理函数xfrm4_rcv和vti_rcv。

  1. --------------------------------------------------
  2. | XFRM子协议结构 | XFRM子处理函数 |
  3. --------------------------------------------------
  4. | ah4_protocol | |
  5. | esp4_protocol | xfrm4_rcv |
  6. | ipcomp4_protocol | |
  7. --------------------------------------------------
  8. | vti_ah4_protocol | |
  9. | vti_esp4_protocol | vti_rcv |
  10. | vti_ipcomp4_protocol | |
  11. --------------------------------------------------

XFRM模块提供xfrm4_protocol_register注册子协议结构,ah4_protocol为xfrm4_protocol类型的结构体变量,与以上的主协议变量ah4_protocol(net_protocol结构体)同名但是不同的数据结构。相同协议号的xfrm4_protocol结构体通过其成员next链接起来,内核中为三种协议(AH、ESP和IPCOMP)定义了链表头,分别为ah4_handlers、esp4_handlers。 协议入口函数(如xfrm4_ah_rcv)从头开始遍历链表(如ah4_handlers链表),依次调用其中的子处理函数。

  1. struct xfrm4_protocol {
  2. int (*handler)(struct sk_buff *skb);
  3. int (*input_handler)(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
  4. int (*cb_handler)(struct sk_buff *skb, int err);
  5. int (*err_handler)(struct sk_buff *skb, u32 info);
  6. struct xfrm4_protocol __rcu *next;
  7. int priority;
  8. };

对于IPv6 IPSec协议,代码框架与IPv4相同,使用xfrm6_protocol_register函数注册协议结构,子协议链条头指针分别为ah6_handlers、esp6_handlers和ipcomp6_handlers分别对应AH、ESP和IPCOMP三种协议。

  1. --------------------------------------------------
  2. | XFRM子协议结构 | XFRM子处理函数 |
  3. --------------------------------------------------
  4. | ah6_protocol | |
  5. | esp6_protocol | xfrm6_rcv |
  6. | ipcomp6_protocol | |
  7. --------------------------------------------------
  8. | vti_ah6_protocol | |
  9. | vti_esp6_protocol | vti6_rcv |
  10. | vti_ipcomp6_protocol | |
  11. --------------------------------------------------

内核版本

Linux-4.15

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/814544
推荐阅读
相关标签
  

闽ICP备14008679号