大家肯定好奇为什么通过ebpf sockops可以提取我们想要的数据 ?
正常来说实现方式有两种,第一种是关键路径上埋钩子函数;第二种是kprobe的粘贴插入。
ebpf sockops 是通过第一种方式实现的,在关键路径上埋钩子函数了,所以想要扩展功能很难哦,一般在内核版本升级时可以提前规划埋好钩子函数。
ebpf sockops 支持那些功能ebpf sockops支持哪些功能(关键看在什么路径上埋了钩子函数),看 下面代码吧
enum {
BPF_SOCK_OPS_VOID,
BPF_SOCK_OPS_TIMEOUT_INIT, /* Should return SYN-RTO value to use or
* -1 if default value should be used
*/
BPF_SOCK_OPS_RWND_INIT, /* Should return initial advertized
* window (in packets) or -1 if default
* value should be used
*/
BPF_SOCK_OPS_TCP_CONNECT_CB, /* Calls BPF program right before an
* active connection is initialized
*/
BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, /* Calls BPF program when an
* active connection is
* established
*/
BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, /* Calls BPF program when a
* passive connection is
* established
*/
BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control
* needs ECN
*/
BPF_SOCK_OPS_BASE_RTT, /* Get base RTT. The correct value is
* based on the path and may be
* dependent on the congestion control
* algorithm. In general it indicates
* a congestion threshold. RTTs above
* this indicate congestion
*/
BPF_SOCK_OPS_RTO_CB, /* Called when an RTO has triggered.
* Arg1: value of icsk_retransmits
* Arg2: value of icsk_rto
* Arg3: whether RTO has expired
*/
BPF_SOCK_OPS_RETRANS_CB, /* Called when skb is retransmitted.
* Arg1: sequence number of 1st byte
* Arg2: # segments
* Arg3: return value of
* tcp_transmit_skb (0 => success)
*/
BPF_SOCK_OPS_STATE_CB, /* Called when TCP changes state.
* Arg1: old_state
* Arg2: new_state
*/
BPF_SOCK_OPS_TCP_LISTEN_CB, /* Called on listen(2), right after
* socket transition to LISTEN state.
*/
};
字面意思已经很明显,就是SYN-RTO超时时间,同时支持客户端和服务端两种模式。
BPF_SOCK_OPS_RWND_INIT字面意思也比较明显了,提取初始的RWND,也同时支持客户端和服务端两种模式。很明显该函数工作在连接建立阶段。
BPF_SOCK_OPS_TCP_CONNECT_CB在主动连接TCP启动之初开始调用,在int tcp_connect(struct sock *sk)函数中被调用。
通俗一点讲,就是在TCP三次握手的第一次(发送SYN报文)时调用。
BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB被动连接是调用,接收到SYN报文时调用。
当然还有一个小众场景,热迁移时TCP连接调用。
BPF_SOCK_OPS_NEEDS_ECN在ECN的模式下调用,具体是在ECN类型的TCP连接阶段调用(发送SYN和接收SYN)。
BPF_SOCK_OPS_BASE_RTT这个功能大家别惦记了,目前只有在tcp_nv的拥塞控制算法中埋了调用点。
当然如果你想用也可以,在自己实现的拥塞控制算法中.init接口中埋好调用点。
BPF_SOCK_OPS_RTO_CB重传超时后调用,但是并不一定能被调用,因为不在主路径上,很可能提前退出,具体代码大家可以自己去看void tcp_retransmit_timer(struct sock *sk)函数。
BPF_SOCK_OPS_RETRANS_CB很明显是在报文重传的时候调用,具体代码在__tcp_retransmit_skb函数中,如果在此统计重传率,那么你一定好检查钩子函数的第5个参数,第5个参数描述了本次重传是否成功。
BPF_SOCK_OPS_STATE_CB在TCP连接状态变化的时候切换,TCP的状态如下:
enum {
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING, /* Now a valid state */
TCP_NEW_SYN_RECV,
TCP_MAX_STATES /* Leave at the end! */
};
利用这个功能你可以统计到TCP连接的状态详细情况,但不一定对你有任何作用。
BPF_SOCK_OPS_TCP_LISTEN_CB在listen系统调用时被调用。
ebpf sockops价值说明1. 坦白说当前ebpf sockops思路是非常好的,可以让我们在外围看见协议栈内部的细节
2. 还是坦白说ebpf sockops的功能比较鸡肋,11个功能,7个是TCP握手阶段,这设计也太神奇了,TCP连接最重要的是TCP握手阶段吗?
3. 在功能领域最实用的是BPF_SOCK_OPS_RETRANS_CB功能,细节不说。
4. 潜在功能,因为BPF_SOCK_OPS_STATE_CB功能我也没想好怎么用。
我期望的ebpf sockops 不仅是能让我们了解TCP握手阶段的细节,更重要的是让我们了解TCP协议栈性能好坏的原因,和出于基于精细化运营要求的数据监控能力(这是工程视角的需求)。
广告如果您正在找网络优化、TCP协议栈、用户态协议栈、高性能网络等方向的工作可以尝试联系我,说不定能帮你找到工作哦。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved