Sitelet https://github.com/Netis/cloud-probe/issues/296
Skip to content

cpworker: GRE output loses the packet direction when service_tag is unset (default 0xFFFFFFFF fills the direction bits) #296

Description

@vaderyang

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 的布局。

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions