【Linux4.1.12源码分析】二层报文发送之GSO条件判断
来源:互联网 发布:网络授权书制作免费 编辑:程序博客网 时间:2024/05/17 23:05
4.1.12内核中,GSO报文的判断和分段的入口函数是validate_xmit_skb,其中使用netif_needs_gso用来判断软件是否要进行GSO分段,skb_gso_segment实现报文的GSO分段,本篇重点讲述GSO分段的判断条件,即netif_needs_gso相关函数。
1、netif_needs_gso函数
static inline bool netif_needs_gso(struct sk_buff *skb, netdev_features_t features){return skb_is_gso(skb) && (!skb_gso_ok(skb, features) || //skb 为gso报文,且feature不包含skb->gso_type 或者 //skb 为gso报文,且skb_ipsummed不为CHECKSUM_PARTIAL和CHECKSUM_UNNECESSARYunlikely((skb->ip_summed != CHECKSUM_PARTIAL) && (skb->ip_summed != CHECKSUM_UNNECESSARY)));}2、skb_gso_ok函数
static inline bool skb_gso_ok(struct sk_buff *skb, netdev_features_t features){return net_gso_ok(features, skb_shinfo(skb)->gso_type) &&//feature包含gso_type 并且skb没有frag_list或者feature包含NETIF_F_FRAGLIST (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST));}3、net_gso_ok函数
static inline bool net_gso_ok(netdev_features_t features, int gso_type){netdev_features_t feature = gso_type << NETIF_F_GSO_SHIFT;/* check flags correspondence */BUILD_BUG_ON(SKB_GSO_TCPV4 != (NETIF_F_TSO >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_UDP != (NETIF_F_UFO >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_DODGY != (NETIF_F_GSO_ROBUST >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_TCPV6 != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_FCOE != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_GRE != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_IPIP != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));return (features & feature) == feature;<span style="white-space:pre"></span>//features 包含feature}
从上面的函数可以判断是否需要进行GSO分段,主要 两个参数features(硬件支持的特性)和skb报文。主要判断条件是features是否包含skb->gso_type。那么我们来看下features是怎么得到的,其实是通过netif_skb_features得到的。
netif_skb_features函数
netdev_features_t netif_skb_features(struct sk_buff *skb){struct net_device *dev = skb->dev;netdev_features_t features = dev->features;//获取设备的featuresu16 gso_segs = skb_shinfo(skb)->gso_segs;if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)features &= ~NETIF_F_GSO_MASK;//如果gso_segs不在规定范围内,则去掉NETIF_F_GSO_MASK标记/* If encapsulation offload request, verify we are testing * hardware encapsulation features instead of standard * features for the netdev */if (skb->encapsulation)features &= dev->hw_enc_features;//如果是封装报文,则feature需要和hw_enc_features取交集, 主流设备均不支持gso offload能力if (skb_vlan_tagged(skb))//如果是vlan报文,刷新feature值features = netdev_intersect_features(features,//features与vlan_feature取交集 dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX);if (dev->netdev_ops->ndo_features_check)features &= dev->netdev_ops->ndo_features_check(skb, dev,features);elsefeatures &= dflt_features_check(skb, dev, features);//刷新vlan feature,最终会调用netdev_intersect_features函数return harmonize_features(skb, features);//更新mpls feature 和csum feature}netdev_intersect_features函数
static inline netdev_features_t netdev_intersect_features(netdev_features_t f1, netdev_features_t f2){if (f1 & NETIF_F_GEN_CSUM)f1 |= (NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);//添加NETIF_F_V4_CSUM | NETIF_F_V6_CSUM 标记if (f2 & NETIF_F_GEN_CSUM)f2 |= (NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);//添加NETIF_F_V4_CSUM | NETIF_F_V6_CSUM 标记f1 &= f2;//取交集if (f1 & NETIF_F_GEN_CSUM)f1 &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM);//删除NETIF_F_V4_CSUM | NETIF_F_V6_CSUM 标记return f1;}harmonize_features函数
static netdev_features_t harmonize_features(struct sk_buff *skb,netdev_features_t features){int tmp;__be16 type;type = skb_network_protocol(skb, &tmp);features = net_mpls_features(skb, features, type);//mpls feature更新if (skb->ip_summed != CHECKSUM_NONE && !can_checksum_protocol(features, type)) {features &= ~NETIF_F_ALL_CSUM;//去掉NETIF_F_ALL_CSUM标记} else if (illegal_highdma(skb->dev, skb)) {features &= ~NETIF_F_SG;//去掉NETIF_F_SG标记}return features;}
判断GSO分段的条件基本搞清楚了,下一篇将分析报文GSO分段是如何实现的。
0 0
- 【Linux4.1.12源码分析】二层报文发送之GSO条件判断
- 【Linux4.1.12源码分析】二层报文发送之报文GSO分段(MAC层)
- 【Linux4.1.12源码分析】二层报文发送之报文GSO分段(IP层)
- 【Linux4.1.12源码分析】二层报文发送之报文GSO分段(UDP)
- 【Linux4.1.12源码分析】二层报文发送之报文GSO分段(TCP)
- 【Linux4.1.12源码分析】二层报文发送之报文GSO分段(skb_segment)
- 【Linux4.1.12源码分析】二层报文发送之dev_queue_xmit
- 【Linux4.1.12源码分析】二层报文发送之net_tx_action
- 【Linux4.1.12源码分析】IP层报文发送之ip_local_out
- 【Linux4.1.12源码分析】IP层报文发送之ip_output
- 【Linux4.1.12源码分析】IP层报文发送之ip_local_out
- 【Linux4.1.12源码分析】二层报文发送之qdisc实现分析
- 【Linux4.1.12源码分析】vxlan报文发送之udp_tunnel_xmit_skb
- 【Linux4.1.12源码分析】vxlan报文发送之iptunnel_xmit
- 【Linux4.1.12源码分析】协议栈报文接收之IP层处理分析(ip_local_deliver)
- 【Linux4.1.12源码分析】协议栈报文接收之IP层处理分析(ip_forward)
- 【Linux4.1.12源码分析】协议栈报文接收之传输层处理分析(UDP)
- 【Linux4.1.12源码分析】协议栈报文接收之netif_receive_skb函数分析
- Atitit 编程语言原理与概论attilax总结
- [LeetCode]--20. Valid Parentheses
- Lock锁学习
- Programming In Scala笔记-第八章、函数与闭包
- Atitit.并发编程原理与概论 attilax总结
- 【Linux4.1.12源码分析】二层报文发送之GSO条件判断
- Java实现验证码(上)
- 自定义控件系列<第一篇>--多维表头
- 面向对象设计原则——单一职责原则(SRP)
- 泛型接口的使用
- Atitit.软件兼容性原理与实践 v3 q326.docx
- Ubuntu命令参考手册
- 小端模式 大端模式
- 面向对象设计原则--里氏替换原则(LSP)和依赖倒置原则(DIP)