Skip to content

feat: support sql server - #11214

Open
yuanchaoa wants to merge 1 commit into
v6.6from
support-sql-server
Open

feat: support sql server#11214
yuanchaoa wants to merge 1 commit into
v6.6from
support-sql-server

Conversation

@yuanchaoa

Copy link
Copy Markdown
Contributor

This PR is for:

  • Agent

feat: support sql server

Checklist

  • Added unit test.

Backport to branches

  • main
  • 6.6

@yuanchaoa
yuanchaoa force-pushed the support-sql-server branch 5 times, most recently from 73b49a3 to ab24cd2 Compare January 16, 2026 06:55
@yuanchaoa
yuanchaoa force-pushed the support-sql-server branch 2 times, most recently from 5c78337 to 0cc7a56 Compare January 24, 2026 09:24
@yuanchaoa
yuanchaoa force-pushed the support-sql-server branch 2 times, most recently from 09d3c60 to c329c66 Compare February 14, 2026 11:00
@yuanchaoa
yuanchaoa force-pushed the support-sql-server branch 7 times, most recently from 052f29e to 767dad0 Compare February 27, 2026 02:08
lzf575
lzf575 previously approved these changes Feb 27, 2026

@lzf575 lzf575 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

server 侧改动没有问题

@lzf575 lzf575 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude review 下这个mr

Comment thread agent/src/ebpf/kernel/include/protocol_inference.h
@SongZhen0704

Copy link
Copy Markdown
Contributor

@claude review 一下代码

@kylewanginchina

Copy link
Copy Markdown
Contributor

@claude review一下当前PR所提交的代码修改

@SongZhen0704

Copy link
Copy Markdown
Contributor

@claude 你好,请 review 一下代码

@claude

claude Bot commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Claude finished @SongZhen0704's task in 6m 36s —— View job


Code Review: SQL Server (TDS) Protocol Support

  • Read and analyze eBPF protocol inference changes
  • Read and analyze Rust SQL Server protocol parser
  • Read and analyze plugin layer changes
  • Read server-side configuration changes
  • Provide comprehensive review feedback

Overall, the PR adds the necessary wiring for SQL Server (TDS protocol) support across the full stack — eBPF inference, Rust L7 parser, server-side config, and querier enum. The structure follows existing patterns well (similar to how Oracle, MySQL, etc. are integrated). However, I found several issues, including one critical bug in the eBPF header parsing.


Critical Issues

1. LENGTH_OFFSET is wrong in eBPF inference (protocol_inference.h:1239)

Per the MS-TDS packet header specification, the 8-byte TDS header layout is:

Offset Size Field
0 1 Type
1 1 Status
2 2 Length (big-endian)
4 2 SPID
6 1 PacketID
7 1 Window

The code defines LENGTH_OFFSET = 1, but the length field is at offset 2, not offset 1. Offset 1 is the Status byte. This means the current code reads [Status, Length_high_byte] as a big-endian u16 instead of the actual [Length_high, Length_low]. This will produce incorrect length values and may cause false negatives/positives in protocol detection.

// Current (incorrect):
#define LENGTH_OFFSET  1

// Should be:
#define LENGTH_OFFSET  2

Fix this →

2. TdsParser is a stub that always fails (plugins/l7/src/sql_server.rs:26-33)

pub fn new(_: &[u8]) -> Self {
    TdsParser::default()  // ignores input payload entirely
}

pub fn parse(&mut self) -> Result<(), ParserError> {
    Err(ParserError::InvalidData)  // always fails
}

The TdsParser discards the input payload in new() and parse() always returns Err. This means:

  • check_payload() always returns None (since tds.sql is never set)
  • parse_payload() always returns L7ParseResult::None for requests (no SQL extracted) and always returns None for responses

The eBPF layer will detect SQL Server traffic, but the userspace parser will never successfully parse any TDS packets. Is this intentional as a first-phase PR with the actual parser coming later? If so, it should be documented. If not, the actual TDS parsing logic is missing.


Moderate Issues

3. Documentation incorrectly marks SqlServer as Enterprise-only

Multiple places in the docs state:

Oracle, SqlServer and TLS is only supported in the Enterprise Edition.

However, in the code (l7_protocol_info.rs), SqlServerInfo is added to both the community and enterprise cfg_if branches (lines 103 and 135), meaning SqlServer is available in community edition. Oracle, by contrast, is only in the enterprise branch. Either:

  • The docs should say "Oracle and TLS" (not SqlServer), or
  • SqlServer should be gated behind cfg(feature = "enterprise") like Oracle

4. Generic #define names risk collision (protocol_inference.h:1236-1244)

#define HEADER_SIZE 8
#define MESSAGE_TYPE_OFFSET  0
#define LENGTH_OFFSET  1
#define WINDOWS_OFFSET  7

These are defined inside the function body but C macros have file scope — they are not scoped to the function. Names like HEADER_SIZE and LENGTH_OFFSET are very generic and could conflict with other definitions. The convention in this file is to prefix with the protocol name (e.g., TNS_HEADER_LENGTH_OFFSET, CUPS_HEADER_SIZE). These should be prefixed with TDS_:

#define TDS_HEADER_SIZE 8
#define TDS_MESSAGE_TYPE_OFFSET  0
#define TDS_LENGTH_OFFSET  2
#define TDS_WINDOWS_OFFSET  7

Fix this →

5. Missing reference link for TDS protocol inference (protocol_inference.h:1231)

As also noted by @yinjiping — other protocol inference functions include reference links (e.g., Oracle references Wireshark dissector code, ISO8583 references Wikipedia). The infer_sql_server_message function should include a reference to the MS-TDS specification:

// ref: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/

Minor Issues

6. Mixed indentation (protocol_inference.h:1258-1259)

Two lines use spaces instead of tabs, inconsistent with the surrounding code:

	char pkt_type = buf[MESSAGE_TYPE_OFFSET];
    __u16 pkt_length = __bpf_ntohs(*(__u16 *) & buf[LENGTH_OFFSET]);  // ← spaces
    char windows = buf[WINDOWS_OFFSET];                                 // ← spaces

7. Dead code: SqlServerLog::reset() is never called (sql_server.rs:281-283)

The reset() method is defined but never invoked anywhere. Either remove it or call it in the appropriate place (e.g., at the start of parse_payload or between sessions).

8. Response status only distinguishes ClientError vs Ok (sql_server.rs:231-233)

if let Some(error_message) = tds.error_message {
    info.error_message = error_message;
    info.resp_status = L7ResponseStatus::ClientError;

TDS errors can also be server errors (severity-based). Currently all errors are mapped to ClientError. When the parser is fully implemented, consider mapping errors based on severity class (e.g., severity >= 20 → ServerError).

9. No unit tests

The PR checklist notes "Added unit test" is unchecked. Other protocol implementations in this codebase include test modules. Tests should at minimum cover:

  • eBPF inference with known TDS packet bytes
  • Correct parsing of SQL Batch and RPC requests
  • Correct parsing of response tokens (error, done row count)

What looks good

  • Protocol ID assignment (63) is consistent across all layers (eBPF common.h, Rust l7_protocol.rs, Go flow.go, ClickHouse enum)
  • Default port 1433 is correct for SQL Server
  • The overall integration follows the established patterns well (wiring into l7_protocol_info.rs, l7_protocol_log.rs, protocol_logs.rs, config defaults, etc.)
  • Blacklist support is properly integrated
  • The ParserError enum in the plugin has good error variant coverage for future TDS parsing

|

@yinjiping

yinjiping commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

@yuanchaoa 可在agent/src/ebpf 目录下

source /opt/rh/devtoolset-11/enable 
make socket-tracer

在 10.50.100.64 中测试下,5.2, 4.19, 4.14 内核是否正常运行(运行下socket_tracer程序)
内核更换版本可以直接修改/boot/grub2/grubenv 然后reboot即可
5.2日志会有: INFO bpf load "socket-trace-bpf-linux-5.2_plus" succeed.
4.19, 4.14 日志: bpf load "socket-trace-bpf-linux-common" succeed.

Comment thread agent/plugins/l7/Cargo.toml Outdated
Comment thread agent/src/common/l7_protocol_info.rs Outdated
Comment thread agent/src/common/l7_protocol_log.rs Outdated
Comment thread agent/src/flow_generator/protocol_logs/sql/mod.rs
Comment thread agent/src/flow_generator/protocol_logs.rs Outdated
Comment thread server/agent_config/template.yaml Outdated
@deepflowio deepflowio deleted a comment from claude Bot Feb 27, 2026
Comment thread agent/src/ebpf/kernel/include/protocol_inference.h
@yuanchaoa
yuanchaoa force-pushed the support-sql-server branch from 767dad0 to cd24437 Compare March 4, 2026 07:07
@yuanchaoa
yuanchaoa changed the base branch from main to v6.6 August 20, 2026 08:29
@yuanchaoa
yuanchaoa force-pushed the support-sql-server branch 2 times, most recently from 130d1ad to 85e64a2 Compare August 24, 2026 06:17
@yuanchaoa

Copy link
Copy Markdown
Contributor Author

@claude review一下当前PR所提交的代码修改

@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @yuanchaoa's task in 9m 5s —— View job


Review complete

  • Read repository instructions and PR context
  • Understand the request and review scope
  • Inspect the diff against origin/v6.6
  • Summarize review findings and recommendations

I reviewed the SQL Server support changes and found four concrete issues worth fixing before merge.

  1. agent/src/ebpf/kernel/include/protocol_inference.h:1262 reads the TDS length from the wrong offset
    The TDS header layout is Type(0) / Status(1) / Length(2..3) / SPID(4..5) / PacketID(6) / Window(7), but infer_sql_server_message() still defines LENGTH_OFFSET as 1. That means pkt_length is computed from [Status, LengthHi] instead of [LengthHi, LengthLo], which can misclassify SQL Server traffic in the eBPF path.
    Fix this →

  2. agent/plugins/l7/src/sql_server.rs:25-30 is still a non-functional stub, so the userspace parser never emits SQL Server logs
    TdsParser::new() ignores the payload and parse() always returns Err(ParserError::InvalidData). Because agent/src/flow_generator/protocol_logs/sql/sql_server.rs:186-203 just calls tds.parse().ok(), check_payload() can never recognize a request and parse_payload() can never produce a request or response log. The current branch wires the protocol through the stack, but the actual parser path is still guaranteed to return L7ParseResult::None.
    Fix this →

  3. agent/src/common/l7_protocol_log.rs:216 does not compile in enterprise builds
    The enterprise L7ProtocolParser enum includes SqlServer(SqlServerLog), but the import list at agent/src/common/l7_protocol_log.rs:41-48 does not bring SqlServerLog into scope. As written, an enterprise build should fail with cannot find type 'SqlServerLog' in this scope.
    Fix this →

  4. The SQL Server feature gating is inconsistent between CE and EE code paths
    The community build now exposes SqlServer in agent/src/common/l7_protocol_info.rs:79-107 and in config defaults at agent/src/config/config.rs:1878-1940, but the non-enterprise parser enum in agent/src/common/l7_protocol_log.rs:157-186 still does not include SqlServer. That means CE can advertise/configure the protocol (including the default 1433 prefilter) without ever being able to instantiate a parser for it. Either the parser needs to be added to the non-enterprise branch too, or the rest of the SqlServer plumbing should stay behind feature = "enterprise".
    Fix this →

I did not re-list the lower-priority style/doc comments that are already present in the PR discussion.

@yuanchaoa

Copy link
Copy Markdown
Contributor Author

@claude review一下当前PR所提交的代码修改, 用中文回复

@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @yuanchaoa's task in 17m 33s —— View job


Todo

  • 读取仓库说明和 PR 上下文
  • 对比 origin/v6.6...HEAD 理解本次改动范围
  • 阅读关键文件并验证潜在问题
  • 输出中文 review 结论

Review 结论

我重点看了 eBPF 协议推断、Rust SQL Server parser,以及 CE / EE 两条接线。当前有 5 个需要在合并前处理的问题;我没有重复 PR 讨论里已经提过的纯文档/格式类意见。

  1. agent/src/ebpf/kernel/include/protocol_inference.h:1262 把 TDS 长度字段读偏了
    TDS 头部是 Type(0) / Status(1) / Length(2..3) / SPID(4..5) / PacketID(6) / Window(7),这里却把 LENGTH_OFFSET 写成了 1,所以 pkt_length 实际读到的是 [Status, LengthHi],不是 [LengthHi, LengthLo]。这会直接影响 eBPF 路径对 SQL Server 流量的判定。
    Fix this →

  2. agent/plugins/l7/src/sql_server.rs:26-31 还是一个恒失败的占位实现,导致 userspace 永远打不出 SQL Server 日志
    TdsParser::new() 丢弃了 payload,parse() 永远返回 InvalidData。而调用侧 agent/src/flow_generator/protocol_logs/sql/sql_server.rs:187-205 又把错误静默吞掉,只依赖 tds.sql / affected_row / status_code / error_message 这些字段。结果就是 check_payload() 永远识别不出请求,parse_payload() 也永远产不出请求/响应日志。当前这版更像是“协议号接通了”,但真正的 SQL Server 解析并没有落地。
    Fix this →

  3. agent/src/common/l7_protocol_log.rs:41-48,216 在 enterprise 构建下会直接编译失败
    这个文件在 enterprise 分支新增了 SqlServer(SqlServerLog),但顶部 import 列表并没有把 SqlServerLog 引进来。也就是说当前代码到了 SqlServer(SqlServerLog) 这里时,SqlServerLog 根本不在作用域里。
    Fix this →

  4. CE / EE 的 feature gating 现在是不一致的,CE 会“暴露协议但拿不到 parser”
    agent/src/config/config.rs:1878-1940 已经把 SqlServer 放进默认端口过滤;agent/src/common/l7_protocol_info.rs:79-107 也把 SqlServerInfo 暴露给了非 enterprise 分支;但 agent/src/common/l7_protocol_log.rs:157-185 的非 enterprise L7ProtocolParser 里并没有 SqlServer。后续 get_parser() 被调用时(例如 agent/src/flow_generator/perf/mod.rs:558),CE 对 L7Protocol::SqlServer 只能拿到 None,等于用户能配置/开启这个协议,但实际永远实例化不出 parser。
    Fix this →

  5. agent/src/flow_generator/protocol_logs/sql/sql_server.rs:171-177,280-283 还会触发 CI 的 dead_code 失败
    obfuscate 是私有字段,但当前只写不读;reset() 也是私有方法,而且没有任何调用点。仓库自己的 CI 在 .github/workflows/agent-verify.yml:47.github/workflows/agent-verify.yml:86 明确用 RUSTFLAGS='-D warnings' cargo check,所以这里的 dead code warning 会被当成 error 处理。
    Fix this →

总结

建议至少先修掉前 4 个问题再合并;第 5 个如果暂时还保留占位实现,也需要一起处理掉,不然 agent verify 很可能直接挂掉。

@yuanchaoa

Copy link
Copy Markdown
Contributor Author

@claude review一下当前PR所提交的代码修改, 用中文回复

@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @yuanchaoa's task in 8m 42s —— View job


Todo

  • 读取仓库里的 CLAUDE.md 和相关说明
  • 对比 origin/v6.6...HEAD,确认本次 PR 的实际改动范围
  • 阅读关键实现并核对是否还存在阻塞合并的问题
  • 用中文整理 review 结论并更新到当前评论

Review 结论

我重新按 origin/v6.6...HEAD 看了一遍当前版本,之前评论里提到的几个问题里,TDS 长度偏移、SqlServerLog 的 import、以及 SqlServer 放进 CE L7ProtocolInfo 的问题已经修掉了。目前我认为还剩下 2 个需要在合并前处理的问题,外加 1 个测试缺口。

  1. agent/plugins/l7/src/sql_server.rs:25-31 仍然是占位实现,导致 SQL Server userspace parser 现在必然不产生日志
    TdsParser::new() 直接丢弃 payload,parse() 永远返回 Err(ParserError::InvalidData)。调用侧 agent/src/flow_generator/protocol_logs/sql/sql_server.rs:187-205 又把这个错误静默吞掉,只根据 tds.sql / affected_row / status_code / error_message 是否被填充来决定是否产生日志。结果就是:check_payload() 识别不出请求,parse_payload() 也不会产出请求/响应日志。当前这版实际上只把协议号和 eBPF 推断接上了,真正的 TDS 解析还没有落地。
    Fix this →

  2. EE/CE 的 gating 还没完全收干净,CE 侧仍然暴露了一个“可配置但不可解析”的 SqlServer
    当前 agent/src/common/l7_protocol_log.rs:159-188 里只有 enterprise 分支才包含 SqlServer(SqlServerLog),所以在 CE 构建下 get_parser(L7Protocol::SqlServer) 会返回 None;这一点从 agent/src/flow_generator/perf/mod.rs:381-383,558 的调用路径可以直接看出来。
    但与此同时,agent/src/config/config.rs:1892,1924 仍然在所有构建里把 SqlServer 放进默认 port_number_prefilterstag_filters,而 agent/crates/public/src/l7_protocol.rs:65-70,117-145 也全局承认了这个协议枚举值。这样 CE 用户仍然可以在配置层看到/填写 SqlServer,但运行时永远实例化不出 parser。要么把这些配置项也一起收进 feature = "enterprise",要么就把 parser 侧同步放开,否则行为是不一致的。
    Fix this →

  3. 测试仍然缺位,尤其是这次新加的 eBPF 推断和 TDS 解析路径
    PR 描述里的 Added unit test 现在还是未勾选状态,而且我没有看到覆盖这次新增 SQL Server 路径的测试。像 agent/src/ebpf/kernel/include/protocol_inference.h:1255-1304 这种长度字段/类型字段很容易回归;如果 parser 后续补齐,也应该至少覆盖 SQL Batch、RPC、response/error 这些基础 case。
    Fix this →

补充说明

  • 我没有重复已经在当前版本里修掉的旧问题。
  • 我尝试补跑 RUSTFLAGS='-D warnings' cargo check 做二次确认,但当前任务没有拿到该命令权限,所以这次结论基于静态审查和 diff 核对。

总体上看,这个 PR 现在的主要问题不是“接线没接上”,而是TDS parser 还没有真正实现;建议至少把第 1 项解决后再合并,第 2 项也最好顺手收干净,避免 CE/EE 行为继续分叉。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants