Skip to content

Commit 3902670

Browse files
tagrawal03meta-codesync[bot]
authored andcommitted
Use PacketBuilder API for LpmSrcLookup fixtures
Summary: Modernized LPM source lookup test fixtures to use the PacketBuilder API instead of hardcoded base64-encoded packets. Also added new BPF flavors (lpm_src_lookup, lpm_src_lookup_gue) with the LPM_SRC_LOOKUP feature enabled, and created a dedicated sudo test file for comprehensive LPM source routing validation. Reviewed By: lima1756 Differential Revision: D87993877 fbshipit-source-id: 8f543028bb77b8179a981444c170f17bc826510f
1 parent 4bf14c9 commit 3902670

1 file changed

Lines changed: 153 additions & 64 deletions

File tree

katran/lib/testing/fixtures/KatranLpmSrcLookupTestFixtures.h

Lines changed: 153 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// @nolint
1+
// clang-format off
22

33
/* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
44
*
@@ -17,91 +17,180 @@
1717
*/
1818

1919
#pragma once
20+
#include <string>
21+
#include <vector>
2022
#include "katran/lib/testing/tools/PacketAttributes.h"
23+
#include "katran/lib/testing/tools/PacketBuilder.h"
2124

2225
namespace katran {
2326
namespace testing {
2427
/**
25-
* Test fixtures for LPM_SRC_LOOKUP feature
28+
* Test fixtures for LPM_SRC_LOOKUP feature.
29+
*
30+
* This feature enables source-based routing by looking up the packet's source
31+
* IP in an LPM (Longest Prefix Match) trie to determine the destination real
32+
* server. When enabled (F_SRC_ROUTING flag on VIP), packets are routed based
33+
* on their source IP prefix match rather than consistent hashing.
34+
*
35+
* Test cases cover:
36+
* - IPv4 source routing with /17 and /24 prefix matches
37+
* - IPv6 source routing with /32 and /64 prefix matches
38+
* - LPM cache hits (repeated source IPs)
39+
* - LPM misses (fallback to consistent hashing)
40+
*
41+
* Note: These fixtures use GUE encapsulation with:
42+
* - Outer IPv6 header with katran source (fc00:2307::1337)
43+
* - UDP header with computed source port and dport=9886
44+
* - Inner original packet
2645
*/
27-
using TestFixture = std::vector<PacketAttributes>;
28-
const TestFixture lpmSrcLookupTestFixtures = {
46+
const std::vector<::katran::PacketAttributes> lpmSrcLookupTestFixtures = {
2947
// 1
30-
{// Ether(src="0x1", dst="0x2")/IP(src="192.168.1.1",
31-
// dst="10.200.1.1")/UDP(sport=31337, dport=80)/"katran test pkt"
32-
.inputPacket =
33-
"AgAAAAAAAQAAAAAACABFAAArAAEAAEARrU/AqAEBCsgBAXppAFAAF5fea2F0cmFuIHRlc3QgcGt0",
34-
.description = "ipv4: lpm cached flow. LPM_SRC_LOOKUP is required",
48+
// ipv4: lpm src lookup /17 - src 192.168.1.2 matches 192.168.0.0/17 rule
49+
// Routes to remote destination fc00::2307:1 (IPv6 real)
50+
{.description = "ipv4: lpm cached flow. LPM_SRC_LOOKUP is required",
3551
.expectedReturnValue = "XDP_TX",
36-
.expectedOutputPacket =
37-
"AADerb6vAgAAAAAACABFAABHAAAAAEARWX8KAA0lCgAAA2h7F8AAMwAARQAAKwABAABAEa1PwKgBAQrIAQF6aQBQABeX3mthdHJhbiB0ZXN0IHBrdA=="},
52+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
53+
.Eth("0x1", "0x2")
54+
.IPv4("192.168.1.2", "10.200.1.1")
55+
.UDP(31337, 80)
56+
.payload("katran test pkt"),
57+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
58+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
59+
.IPv6("fc00:2307::1337", "fc00::2307:1", 64, 0, 0)
60+
.UDP(31595, 9886)
61+
.IPv4("192.168.1.2", "10.200.1.1")
62+
.UDP(31337, 80)
63+
.payload("katran test pkt")
64+
},
3865
// 2
39-
{// Ether(src="0x1", dst="0x2")/IP(src="192.168.1.2",
40-
// dst="10.200.1.1")/UDP(sport=31337, dport=80)/"katran test pkt"
41-
.inputPacket =
42-
"AgAAAAAAAQAAAAAACABFAAArAAEAAEARrU7AqAECCsgBAXppAFAAF5fda2F0cmFuIHRlc3QgcGt0",
43-
.description = "ipv4: lpm src lookup /17. LPM_SRC_LOOKUP is required",
66+
// ipv4: lpm src lookup /17 - src 192.168.1.2 matches 192.168.0.0/17 rule
67+
// Routes to remote destination fc00::2307:1 (IPv6 real)
68+
{.description = "ipv4: lpm src lookup /17. LPM_SRC_LOOKUP is required",
4469
.expectedReturnValue = "XDP_TX",
45-
.expectedOutputPacket =
46-
"AADerb6vAgAAAAAAht1gAAAAADMRQPwAIwcAAAAAAAAAAAAAEzf8AAAAAAAAAAAAAAAjBwABe2sXwAAzAABFAAArAAEAAEARrU7AqAECCsgBAXppAFAAF5fda2F0cmFuIHRlc3QgcGt0"},
70+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
71+
.Eth("0x1", "0x2")
72+
.IPv4("192.168.1.2", "10.200.1.1")
73+
.UDP(31337, 80)
74+
.payload("katran test pkt"),
75+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
76+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
77+
.IPv6("fc00:2307::1337", "fc00::2307:1", 64, 0, 0)
78+
.UDP(31595, 9886)
79+
.IPv4("192.168.1.2", "10.200.1.1")
80+
.UDP(31337, 80)
81+
.payload("katran test pkt")
82+
},
4783
// 3
48-
{// Ether(src="0x1", dst="0x2")/IP(src="192.168.100.1",
49-
// dst="10.200.1.1")/UDP(sport=31337, dport=80)/"katran test pkt"
50-
.inputPacket =
51-
"AgAAAAAAAQAAAAAACABFAAArAAEAAEARSk/AqGQBCsgBAXppAFAAFzTea2F0cmFuIHRlc3QgcGt0",
52-
.description = "ipv4: lpm src lookup /24 . LPM_SRC_LOOKUP is required",
84+
// ipv4: lpm src lookup /24 - src 192.168.100.1 matches 192.168.100.0/24 rule
85+
// Routes to remote destination fc00::2307:2 (IPv6 real)
86+
{.description = "ipv4: lpm src lookup /24 . LPM_SRC_LOOKUP is required",
5387
.expectedReturnValue = "XDP_TX",
54-
.expectedOutputPacket =
55-
"AADerb6vAgAAAAAAht1gAAAAADMRQPwAIwcAAAAAAAAAAAAAEzf8AAAAAAAAAAAAAAAjBwACHmgXwAAzAABFAAArAAEAAEARSk/AqGQBCsgBAXppAFAAFzTea2F0cmFuIHRlc3QgcGt0"},
88+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
89+
.Eth("0x1", "0x2")
90+
.IPv4("192.168.100.1", "10.200.1.1")
91+
.UDP(31337, 80)
92+
.payload("katran test pkt"),
93+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
94+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
95+
.IPv6("fc00:2307::1337", "fc00::2307:2", 64, 0, 0)
96+
.UDP(7784, 9886)
97+
.IPv4("192.168.100.1", "10.200.1.1")
98+
.UDP(31337, 80)
99+
.payload("katran test pkt")
100+
},
56101
// 4
57-
{// Ether(src="0x1", dst="0x2")/IP(src="192.168.200.1",
58-
// dst="10.200.1.1")/UDP(sport=31337, dport=80)/"katran test pkt"
59-
.inputPacket =
60-
"AgAAAAAAAQAAAAAACABFAAArAAEAAEAR5k7AqMgBCsgBAXppAFAAF9Dda2F0cmFuIHRlc3QgcGt0",
61-
.description = "ipv4: lpm miss. LPM_SRC_LOOKUP is required",
102+
// ipv4: lpm miss - src 192.168.200.1 does NOT match any LPM rule
103+
// Falls back to consistent hashing, routes to 10.0.0.3 (IPv4 real)
104+
// GUE encap with outer IPv4
105+
{.description = "ipv4: lpm miss. LPM_SRC_LOOKUP is required",
62106
.expectedReturnValue = "XDP_TX",
63-
.expectedOutputPacket =
64-
"AADerb6vAgAAAAAACABFAABHAAAAAEARWX8KAA0lCgAAA6F7F8AAMwAARQAAKwABAABAEeZOwKjIAQrIAQF6aQBQABfQ3WthdHJhbiB0ZXN0IHBrdA=="},
107+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
108+
.Eth("0x1", "0x2")
109+
.IPv4("192.168.200.1", "10.200.1.1")
110+
.UDP(31337, 80)
111+
.payload("katran test pkt"),
112+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
113+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
114+
.IPv4("10.0.13.37", "10.0.0.3", 64, 0, 0)
115+
.UDP(41339, 9886)
116+
.IPv4("192.168.200.1", "10.200.1.1")
117+
.UDP(31337, 80)
118+
.payload("katran test pkt")
119+
},
65120
// 5
66-
{// Ether(src="0x1", dst="0x2")/IPv6(src="fc00:2::2",
67-
// dst="fc00:1::1")/TCP(sport=31337, dport=80,flags="A")/"katran test
68-
// pkt"
69-
.inputPacket =
70-
"AgAAAAAAAQAAAAAAht1gAAAAACMGQPwAAAIAAAAAAAAAAAAAAAL8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgAP1OAABrYXRyYW4gdGVzdCBwa3Q=",
71-
.description = "ipv6: lpm src lookup /64. LPM_SRC_LOOKUP is required",
121+
// ipv6: lpm src lookup /64 - src fc00:2::2 matches fc00:2::/64 rule
122+
// Routes to remote destination fc00::2307:10 (IPv6 real)
123+
{.description = "ipv6: lpm src lookup /64. LPM_SRC_LOOKUP is required",
72124
.expectedReturnValue = "XDP_TX",
73-
.expectedOutputPacket =
74-
"AADerb6vAgAAAAAAht1gAAAAAFMRQPwAIwcAAAAAAAAAAAAAEzf8AAAAAAAAAAAAAAAjBwAQemkXwABTAABgAAAAACMGQPwAAAIAAAAAAAAAAAAAAAL8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgAP1OAABrYXRyYW4gdGVzdCBwa3Q="},
125+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
126+
.Eth("0x1", "0x2")
127+
.IPv6("fc00:2::2", "fc00:1::1")
128+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
129+
.payload("katran test pkt"),
130+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
131+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
132+
.IPv6("fc00:2307::1337", "fc00::2307:10", 64, 0, 0)
133+
.UDP(31337, 9886)
134+
.IPv6("fc00:2::2", "fc00:1::1")
135+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
136+
.payload("katran test pkt")
137+
},
75138
// 6
76-
{// Ether(src="0x1", dst="0x2")/IPv6(src="fc00:2307::1",
77-
// dst="fc00:1::1")/TCP(sport=31337, dport=80,flags="A")/"katran test
78-
// pkt"
79-
.inputPacket =
80-
"AgAAAAAAAQAAAAAAht1gAAAAACMGQPwAIwcAAAAAAAAAAAAAAAH8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgANpKAABrYXRyYW4gdGVzdCBwa3Q=",
81-
.description = "ipv6: lpm src lookup /32. LPM_SRC_LOOKUP is required",
139+
// ipv6: lpm src lookup /32 - src fc00:2307::1 matches fc00:2307::/64 rule
140+
// (which is more specific than /32)
141+
// Routes to remote destination fc00::2307:4 (IPv6 real)
142+
{.description = "ipv6: lpm src lookup /32. LPM_SRC_LOOKUP is required",
82143
.expectedReturnValue = "XDP_TX",
83-
.expectedOutputPacket =
84-
"AADerb6vAgAAAAAAht1gAAAAAFMRQPwAIwcAAAAAAAAAAAAAEzf8AAAAAAAAAAAAAAAjBwAEemkXwABTAABgAAAAACMGQPwAIwcAAAAAAAAAAAAAAAH8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgANpKAABrYXRyYW4gdGVzdCBwa3Q="},
144+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
145+
.Eth("0x1", "0x2")
146+
.IPv6("fc00:2307::1", "fc00:1::1")
147+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
148+
.payload("katran test pkt"),
149+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
150+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
151+
.IPv6("fc00:2307::1337", "fc00::2307:4", 64, 0, 0)
152+
.UDP(31337, 9886)
153+
.IPv6("fc00:2307::1", "fc00:1::1")
154+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
155+
.payload("katran test pkt")
156+
},
85157
// 7
86-
{// Ether(src="0x1", dst="0x2")/IPv6(src="fc00:2308:1::1",
87-
// dst="fc00:1::1")/TCP(sport=31337, dport=80,flags="A")/"katran test
88-
// pkt"
89-
.inputPacket =
90-
"AgAAAAAAAQAAAAAAht1gAAAAACMGQPwAIwgAAQAAAAAAAAAAAAH8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgANpIAABrYXRyYW4gdGVzdCBwa3Q=",
91-
.description = "ipv6: lpm miss. LPM_SRC_LOOKUP is required",
158+
// ipv6: lpm miss - src fc00:2308:1::1 does NOT match any LPM rule
159+
// Falls back to consistent hashing, routes to fc00::1 (IPv6 real)
160+
{.description = "ipv6: lpm miss. LPM_SRC_LOOKUP is required",
92161
.expectedReturnValue = "XDP_TX",
93-
.expectedOutputPacket =
94-
"AADerb6vAgAAAAAAht1gAAAAAFMRQPwAIwcAAAAAAAAAAAAAEzf8AAAAAAAAAAAAAAAAAAABemkXwABTAABgAAAAACMGQPwAIwgAAQAAAAAAAAAAAAH8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgANpIAABrYXRyYW4gdGVzdCBwa3Q="},
162+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
163+
.Eth("0x1", "0x2")
164+
.IPv6("fc00:2308:1::1", "fc00:1::1")
165+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
166+
.payload("katran test pkt"),
167+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
168+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
169+
.IPv6("fc00:2307::1337", "fc00::1", 64, 0, 0)
170+
.UDP(31337, 9886)
171+
.IPv6("fc00:2308:1::1", "fc00:1::1")
172+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
173+
.payload("katran test pkt")
174+
},
95175
// 8
96-
{// Ether(src="0x1", dst="0x2")/IPv6(src="fc00:2::1",
97-
// dst="fc00:1::1")/TCP(sport=31337, dport=80,flags="A")/"katran test
98-
// pkt"
99-
.inputPacket =
100-
"AgAAAAAAAQAAAAAAht1gAAAAACMGQPwAAAIAAAAAAAAAAAAAAAH8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgAP1PAABrYXRyYW4gdGVzdCBwa3Q=",
101-
.description = "ipv6: lpm cached flow. LPM_SRC_LOOKUP is required",
176+
// ipv6: lpm cached flow - src fc00:2::1 matches fc00:2::/64 rule
177+
// Routes to remote destination fc00::2307:10 (IPv6 real)
178+
// This tests the LRU cache hit path
179+
{.description = "ipv6: lpm cached flow. LPM_SRC_LOOKUP is required",
102180
.expectedReturnValue = "XDP_TX",
103-
.expectedOutputPacket =
104-
"AADerb6vAgAAAAAAht1gAAAAAFMRQPwAIwcAAAAAAAAAAAAAEzf8AAAAAAAAAAAAAAAAAAADemkXwABTAABgAAAAACMGQPwAAAIAAAAAAAAAAAAAAAH8AAABAAAAAAAAAAAAAAABemkAUAAAAAAAAAAAUBAgAP1PAABrYXRyYW4gdGVzdCBwa3Q="},
181+
.inputPacketBuilder = katran::testing::PacketBuilder::newPacket()
182+
.Eth("0x1", "0x2")
183+
.IPv6("fc00:2::1", "fc00:1::1")
184+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
185+
.payload("katran test pkt"),
186+
.expectedOutputPacketBuilder = katran::testing::PacketBuilder::newPacket()
187+
.Eth("02:00:00:00:00:00", "00:00:de:ad:be:af")
188+
.IPv6("fc00:2307::1337", "fc00::2307:10", 64, 0, 0)
189+
.UDP(31337, 9886)
190+
.IPv6("fc00:2::1", "fc00:1::1")
191+
.TCP(31337, 80, 0, 0, 8192, TH_ACK)
192+
.payload("katran test pkt")
193+
},
105194
};
106195

107196
} // namespace testing

0 commit comments

Comments
 (0)