diff --git a/feature/policy_forwarding/decapsulation/otg_tests/ip_guev1_static_decap_subnet_range/ip_guev1_static_decap_subnet_range_test.go b/feature/policy_forwarding/decapsulation/otg_tests/ip_guev1_static_decap_subnet_range/ip_guev1_static_decap_subnet_range_test.go index 2cbf5a05bc5..15cad9b41b1 100644 --- a/feature/policy_forwarding/decapsulation/otg_tests/ip_guev1_static_decap_subnet_range/ip_guev1_static_decap_subnet_range_test.go +++ b/feature/policy_forwarding/decapsulation/otg_tests/ip_guev1_static_decap_subnet_range/ip_guev1_static_decap_subnet_range_test.go @@ -482,7 +482,13 @@ func gueDecapInnerIpv4Traffic(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra stopCapture(t, ate) if trafficValidation { verifyTrafficFlow(t, ate, trafficID, true) - verifyCaptureDscpTtlValue(t, ate, "port2", int(innerDscpValue), int(innerTTL-1)) + if verifyCounters { + // PF-1.4.1 / PF-1.4.2: decapsulate — verify inner DSCP and TTL + verifyCaptureDscpTtlValue(t, ate, "port2", int(innerDscpValue), int(innerTTL-1)) + } else { + // PF-1.4.5 / PF-1.4.6: pass-through — verify outer packet unmodified (no decap) + verifyPassThroughGuePacket(t, ate, "port2") + } } else { verifyTrafficFlow(t, ate, trafficID, false) } @@ -501,7 +507,13 @@ func gueDecapInnerIpv6Traffic(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra stopCapture(t, ate) if trafficValidation { verifyTrafficFlow(t, ate, trafficID, true) - verifyCaptureDscpTtlValue(t, ate, "port2", int(innerDscpValue), int(innerTTL-1)) + if verifyCounters { + // PF-1.4.1 / PF-1.4.2: decapsulate — verify inner DSCP and TTL + verifyCaptureDscpTtlValue(t, ate, "port2", int(innerDscpValue), int(innerTTL-1)) + } else { + // PF-1.4.5 / PF-1.4.6: pass-through — verify outer packet unmodified (no decap) + verifyPassThroughGuePacket(t, ate, "port2") + } } else { verifyTrafficFlow(t, ate, trafficID, false) } @@ -613,7 +625,7 @@ func verifyCaptureDscpTtlValue(t *testing.T, ate *ondatra.ATEDevice, port string if ip6Layer := packet.Layer(layers.LayerTypeIPv6); ip6Layer != nil { ip6, _ := ip6Layer.(*layers.IPv6) if ip6.SrcIP.Equal(net.ParseIP(ipv6Src)) { - dscpValue := ip6.TrafficClass >> 2 + dscpValue := ip6.TrafficClass ttlVal := ip6.HopLimit if int(dscpValue) == dscp && int(ttlVal) == ttl { t.Logf("PASS: IPv6 DSCP value %v and TTL value %v are Preserved", dscp, ttl) @@ -657,3 +669,26 @@ func waitForBGPSession(t *testing.T, dut *ondatra.DUTDevice, wantEstablished boo } } } +func verifyPassThroughGuePacket(t *testing.T, ate *ondatra.ATEDevice, port string) { + pcapfilename := processCapture(t, ate, port) + handle, err := pcap.OpenOffline(pcapfilename) + if err != nil { + t.Fatal(err) + } + defer handle.Close() + packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) + for packet := range packetSource.Packets() { + if ip6Layer := packet.Layer(layers.LayerTypeIPv6); ip6Layer != nil { + ip6, _ := ip6Layer.(*layers.IPv6) + if ip6.SrcIP.Equal(net.ParseIP(atePort1.IPv6)) { + expectedTTL := uint8(outerTTL - 1) + if ip6.HopLimit == expectedTTL { + t.Logf("PASS: GUE pass-through packet verified: outer src=%s, TTL=%d (decremented by 1)", atePort1.IPv6, ip6.HopLimit) + return + } + t.Fatalf("ERROR: Outer TTL mismatch in pass-through. Expected: %d, Got: %d", expectedTTL, ip6.HopLimit) + } + } + } + t.Fatalf("ERROR: Could not find GUE pass-through packet with outer src IP (%s) in capture", atePort1.IPv6) +}