Summary
The GRE output encodes the packet direction in the high 4 bits of the GRE key (output_gre.c:71):
gre_hdr->keybit = htonl(output->service_tag | (direct << 28));
docs/USAGE-CPWORKER.md describes gre.service_tag as "default 0xFFFFFFFF, 28 bits (0x0-0xFFFFFFF); the high 4 bits of the key carry the direction". The default does not fit in 28 bits: when service_tag is not set, its high nibble is already 0xF, the OR leaves it unchanged, and every packet is sent with key 0xFFFFFFFF, whatever its direction.
cpdaemon produces exactly this config. For a CPM GRE strategy without a service tag, worker_task_builder.go leaves Gre.ServiceTag nil (json:"service_tag,omitempty"), so cpworker falls back to 0xFFFFFFFF. With a req_pattern, the request/response information is lost for all mirrored traffic.
VXLAN v1 handles the same case without loss: cpdaemon sends vni1 = 0xFFFFFF, and the tag layout keeps the direction nibble (VXLAN-WIRE-FORMAT.md §4). ZMQ stores the direction in its own bit-field (make_mpls_hdr).
Reproduction (0.9.x d302572)
I parsed a config with a gre output to 127.0.0.1, created the output with gre_output_new_from_cfg, and read the GRE packets back from a raw IPPROTO_GRE socket:
config (no service_tag) -> service_tag 0xFFFFFFFF
dir 0 (NONCHECK): GRE key 0xFFFFFFFF
dir 1 (INCOMING): GRE key 0xFFFFFFFF
dir 2 (OUTGOING): GRE key 0xFFFFFFFF
config "service_tag": 291 -> service_tag 0x00000123
dir 0: GRE key 0x00000123
dir 1: GRE key 0x10000123
dir 2: GRE key 0x20000123
Expected
The high nibble carries the direction whatever the service tag is. For example, mask the tag to 28 bits when building the key ((service_tag & 0x0FFFFFFF) | (direct << 28)), and make the default/"no service tag" value fit in 28 bits (0xFFFFFFF), in line with VXLAN v1. Document the GRE key layout, including the no-service-tag value, the way VXLAN-WIRE-FORMAT.md does.
中文原文
GRE 输出把方向写在 GRE key 的高 4 位:keybit = htonl(service_tag | (direct << 28))。USAGE 写明 gre.service_tag 默认 0xFFFFFFFF、有效范围 28 位、key 的高 4 位携带方向,但默认值本身超出 28 位:未配置 service_tag 时高 4 位已是 0xF,或运算后不变,于是无论方向如何,每个包的 key 都是 0xFFFFFFFF。cpdaemon 正会生成这种配置:CPM 的 GRE 策略没有 service tag 时,Gre.ServiceTag 为 nil(omitempty),cpworker 回落到默认值,配置了 req_pattern 时所有镜像流量都丢失请求/响应信息。VXLAN v1 在同样情况下不丢方向(cpdaemon 下发 0xFFFFFF,标签布局保留方向位),ZMQ 的方向也在独立的位域里。在 0.9.x d302572 上用 raw socket 抓包复现(见上)。期望不论 service tag 为何值,高 4 位都携带方向:构造 key 时把 tag 掩码到 28 位,默认值改为能放进 28 位的 0xFFFFFFF,并像 VXLAN-WIRE-FORMAT.md 那样记载 GRE key 的布局。
Summary
The GRE output encodes the packet direction in the high 4 bits of the GRE key (
output_gre.c:71):docs/USAGE-CPWORKER.md describes
gre.service_tagas "default0xFFFFFFFF, 28 bits (0x0-0xFFFFFFF); the high 4 bits of the key carry the direction". The default does not fit in 28 bits: whenservice_tagis not set, its high nibble is already0xF, the OR leaves it unchanged, and every packet is sent with key0xFFFFFFFF, whatever its direction.cpdaemon produces exactly this config. For a CPM GRE strategy without a service tag,
worker_task_builder.goleavesGre.ServiceTagnil (json:"service_tag,omitempty"), so cpworker falls back to0xFFFFFFFF. With areq_pattern, the request/response information is lost for all mirrored traffic.VXLAN v1 handles the same case without loss: cpdaemon sends
vni1 = 0xFFFFFF, and the tag layout keeps the direction nibble (VXLAN-WIRE-FORMAT.md §4). ZMQ stores the direction in its own bit-field (make_mpls_hdr).Reproduction (0.9.x d302572)
I parsed a config with a
greoutput to 127.0.0.1, created the output withgre_output_new_from_cfg, and read the GRE packets back from a rawIPPROTO_GREsocket:Expected
The high nibble carries the direction whatever the service tag is. For example, mask the tag to 28 bits when building the key (
(service_tag & 0x0FFFFFFF) | (direct << 28)), and make the default/"no service tag" value fit in 28 bits (0xFFFFFFF), in line with VXLAN v1. Document the GRE key layout, including the no-service-tag value, the way VXLAN-WIRE-FORMAT.md does.中文原文
GRE 输出把方向写在 GRE key 的高 4 位:keybit = htonl(service_tag | (direct << 28))。USAGE 写明 gre.service_tag 默认 0xFFFFFFFF、有效范围 28 位、key 的高 4 位携带方向,但默认值本身超出 28 位:未配置 service_tag 时高 4 位已是 0xF,或运算后不变,于是无论方向如何,每个包的 key 都是 0xFFFFFFFF。cpdaemon 正会生成这种配置:CPM 的 GRE 策略没有 service tag 时,Gre.ServiceTag 为 nil(omitempty),cpworker 回落到默认值,配置了 req_pattern 时所有镜像流量都丢失请求/响应信息。VXLAN v1 在同样情况下不丢方向(cpdaemon 下发 0xFFFFFF,标签布局保留方向位),ZMQ 的方向也在独立的位域里。在 0.9.x d302572 上用 raw socket 抓包复现(见上)。期望不论 service tag 为何值,高 4 位都携带方向:构造 key 时把 tag 掩码到 28 位,默认值改为能放进 28 位的 0xFFFFFFF,并像 VXLAN-WIRE-FORMAT.md 那样记载 GRE key 的布局。