Skip to content

Commit bcbb0e7

Browse files
author
Tomasz Osiński
authored
[SDFAB-192] Report VXLAN-encaped packets to support end-host INT (#275)
* Report VXLAN-encaped packets * Add VXLAN pkt types for the INT-related PTF tests
1 parent 47c9c6b commit bcbb0e7

8 files changed

Lines changed: 125 additions & 30 deletions

File tree

p4src/include/control/int.p4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ control IntEgress (
417417
fabric_md.int_report_md.eg_tstamp = eg_prsr_md.global_tstamp[31:0];
418418
fabric_md.int_report_md.ip_eth_type = fabric_md.bridged.base.ip_eth_type;
419419
fabric_md.int_report_md.flow_hash = fabric_md.bridged.base.inner_hash;
420-
// fabric_md.int_report_md.gtpu_presence set by the parser
420+
// fabric_md.int_report_md.encap_presence set by the parser
421421
}
422422

423423
@hidden

p4src/include/control/int_parser.p4

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ parser IntReportParser (packet_in packet,
5454
fabric_md.int_report_md.ip_eth_type = ETHERTYPE_IPV4;
5555
fabric_md.int_report_md.report_type = IntReportType_t.DROP;
5656
fabric_md.int_report_md.mirror_type = FabricMirrorType_t.INVALID;
57-
fabric_md.int_report_md.gtpu_presence = fabric_md.bridged.base.gtpu_presence;
57+
fabric_md.int_report_md.encap_presence = fabric_md.bridged.base.encap_presence;
5858
fabric_md.int_report_md.flow_hash = fabric_md.bridged.base.inner_hash;
5959

6060
/** report_fixed_header **/
@@ -174,11 +174,12 @@ parser IntReportParser (packet_in packet,
174174

175175
state check_eth_type {
176176
packet.extract(hdr.eth_type);
177-
transition select(hdr.eth_type.value, fabric_md.int_report_md.gtpu_presence) {
177+
transition select(hdr.eth_type.value, fabric_md.int_report_md.encap_presence) {
178178
(ETHERTYPE_MPLS, _): strip_mpls;
179-
(ETHERTYPE_IPV4, GtpuPresence.NONE): handle_ipv4;
180-
(ETHERTYPE_IPV4, GtpuPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
181-
(ETHERTYPE_IPV4, GtpuPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
179+
(ETHERTYPE_IPV4, EncapPresence.NONE): handle_ipv4;
180+
(ETHERTYPE_IPV4, EncapPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
181+
(ETHERTYPE_IPV4, EncapPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
182+
(ETHERTYPE_IPV4, EncapPresence.VXLAN): strip_ipv4_udp_vxlan;
182183
default: reject;
183184
}
184185
}
@@ -188,10 +189,11 @@ parser IntReportParser (packet_in packet,
188189
state strip_mpls {
189190
packet.advance(MPLS_HDR_BYTES * 8);
190191
bit<IP_VER_BITS> ip_ver = packet.lookahead<bit<IP_VER_BITS>>();
191-
transition select(ip_ver, fabric_md.int_report_md.gtpu_presence) {
192-
(IP_VERSION_4, GtpuPresence.NONE): handle_ipv4;
193-
(IP_VERSION_4, GtpuPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
194-
(IP_VERSION_4, GtpuPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
192+
transition select(ip_ver, fabric_md.int_report_md.encap_presence) {
193+
(IP_VERSION_4, EncapPresence.NONE): handle_ipv4;
194+
(IP_VERSION_4, EncapPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
195+
(IP_VERSION_4, EncapPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
196+
(IP_VERSION_4, EncapPresence.VXLAN): strip_ipv4_udp_vxlan;
195197
default: reject;
196198
}
197199
}
@@ -207,6 +209,15 @@ parser IntReportParser (packet_in packet,
207209
transition handle_ipv4;
208210
}
209211

212+
state strip_ipv4_udp_vxlan {
213+
packet.advance((IPV4_HDR_BYTES + UDP_HDR_BYTES + VXLAN_HDR_BYTES) * 8);
214+
// Skip the Ethernet header.
215+
// It will be removed from a packet and the outer Ethernet will be used
216+
// as the inner Ethernet header.
217+
packet.advance((ETH_HDR_BYTES) * 8);
218+
transition handle_ipv4;
219+
}
220+
210221
state handle_ipv4 {
211222
// Extract only the length, required later to compute the lenght of the
212223
// report encap headers.

p4src/include/control/spgw.p4

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ control DecapGtpu(inout ingress_headers_t hdr,
1919
hdr.gtpu.setInvalid();
2020
hdr.gtpu_options.setInvalid();
2121
hdr.gtpu_ext_psc.setInvalid();
22-
fabric_md.bridged.base.gtpu_presence = GtpuPresence.NONE;
22+
fabric_md.bridged.base.encap_presence = EncapPresence.NONE;
2323
}
2424
@hidden
2525
action decap_inner_tcp() {
@@ -348,7 +348,7 @@ control SpgwIngress(
348348
}
349349
// PDRs
350350
if (fabric_md.spgw.src_iface == SpgwInterface.ACCESS &&
351-
fabric_md.bridged.base.gtpu_presence != GtpuPresence.NONE) {
351+
fabric_md.bridged.base.encap_presence != EncapPresence.NONE) {
352352
uplink_pdrs.apply();
353353
} else if (fabric_md.spgw.src_iface == SpgwInterface.CORE ||
354354
fabric_md.spgw.src_iface == SpgwInterface.FROM_DBUF) {
@@ -410,7 +410,7 @@ control SpgwEgress(
410410
hdr.outer_gtpu.msglen = hdr.ipv4.total_len;
411411
hdr.outer_gtpu.ex_flag = 0;
412412
#ifdef WITH_INT
413-
fabric_md.int_report_md.gtpu_presence = GtpuPresence.GTPU_ONLY;
413+
fabric_md.int_report_md.encap_presence = EncapPresence.GTPU_ONLY;
414414
#endif // WITH_INT
415415
}
416416

@@ -432,7 +432,7 @@ control SpgwEgress(
432432
hdr.outer_gtpu_ext_psc.setValid();
433433
hdr.outer_gtpu_ext_psc.qfi = qfi;
434434
#ifdef WITH_INT
435-
fabric_md.int_report_md.gtpu_presence = GtpuPresence.GTPU_WITH_PSC;
435+
fabric_md.int_report_md.encap_presence = EncapPresence.GTPU_WITH_PSC;
436436
#endif // WITH_INT
437437
}
438438

p4src/include/define.p4

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define GTPU_EXT_PSC_HDR_BYTES 4
2525
#define MPLS_HDR_BYTES 4
2626
#define VLAN_HDR_BYTES 4
27+
#define VXLAN_HDR_BYTES 8
2728

2829
#define PKT_INSTANCE_TYPE_NORMAL 0
2930
#define PKT_INSTANCE_TYPE_INGRESS_CLONE 1
@@ -61,10 +62,15 @@ enum bit<8> SpgwInterface {
6162
FROM_DBUF = 0x3
6263
}
6364

64-
enum bit<2> GtpuPresence {
65+
// According to our design choice, we report only the inner headers to the INT collector.
66+
// The EncapPresence keeps track of the encapsulation protocol in use.
67+
// The EncapPresence is further needed by the egress INT parser to strip out the outer encapsulation headers
68+
// and put only inner headers in an INT report.
69+
enum bit<2> EncapPresence {
6570
NONE = 0x0,
6671
GTPU_ONLY = 0x1,
67-
GTPU_WITH_PSC = 0x2
72+
GTPU_WITH_PSC = 0x2,
73+
VXLAN = 0x3
6874
}
6975

7076
const bit<16> GTPU_UDP_PORT = 2152;
@@ -131,6 +137,8 @@ const vlan_id_t DEFAULT_VLAN_ID = 12w4094;
131137
const bit<8> DEFAULT_MPLS_TTL = 64;
132138
const bit<8> DEFAULT_IPV4_TTL = 64;
133139

140+
const bit<16> VXLAN_UDP_PORT = 4789;
141+
134142
// The recirculation port uses the same number for all HW pipes. The actual port
135143
// ID (DP_ID) can be obtained by prefixing the HW pipe ID (2 bits).
136144
const bit<7> RECIRC_PORT_NUMBER = 7w68;

p4src/include/header.p4

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ header icmp_t {
121121
// Other optional fields...
122122
}
123123

124+
header vxlan_t {
125+
bit<8> flags;
126+
bit<24> reserved;
127+
bit<24> vni;
128+
bit<8> reserved_2;
129+
}
124130

125131
// GTPU v1 -- 3GPP TS 29.281 version 15.7.0
126132
// https://www.etsi.org/deliver/etsi_ts/129200_129299/129281/15.07.00_60/ts_129281v150700p.pdf
@@ -234,7 +240,7 @@ header local_report_header_t {
234240
@pa_no_overlay("egress", "fabric_md.int_report_md.ip_eth_type")
235241
@pa_no_overlay("egress", "fabric_md.int_report_md.report_type")
236242
@pa_no_overlay("egress", "fabric_md.int_report_md.flow_hash")
237-
@pa_no_overlay("egress", "fabric_md.int_report_md.gtpu_presence")
243+
@pa_no_overlay("egress", "fabric_md.int_report_md.encap_presence")
238244
header int_report_metadata_t {
239245
BridgedMdType_t bmd_type;
240246
@padding bit<5> _pad0;
@@ -252,7 +258,7 @@ header int_report_metadata_t {
252258
bit<8> drop_reason;
253259
bit<16> ip_eth_type;
254260
@padding bit<6> _pad5;
255-
GtpuPresence gtpu_presence;
261+
EncapPresence encap_presence;
256262
@padding bit<6> _pad6;
257263
IntReportType_t report_type;
258264
flow_hash_t flow_hash;
@@ -280,7 +286,7 @@ struct bridged_metadata_base_t {
280286
bool is_multicast;
281287
fwd_type_t fwd_type;
282288
vlan_id_t vlan_id;
283-
GtpuPresence gtpu_presence;
289+
EncapPresence encap_presence;
284290
// bit<3> vlan_pri;
285291
// bit<1> vlan_cfi;
286292
bit<8> mpls_ttl;
@@ -414,6 +420,9 @@ struct ingress_headers_t {
414420
gtpu_t gtpu;
415421
gtpu_options_t gtpu_options;
416422
gtpu_ext_psc_t gtpu_ext_psc;
423+
vxlan_t vxlan;
424+
ethernet_t inner_ethernet;
425+
eth_type_t inner_eth_type;
417426
ipv4_t inner_ipv4;
418427
tcp_t inner_tcp;
419428
udp_t inner_udp;

p4src/include/parser.p4

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ parser FabricIngressParser (packet_in packet,
3333
#ifdef WITH_INT
3434
fabric_md.bridged.int_bmd.drop_reason = IntDropReason_t.DROP_REASON_UNKNOWN;
3535
#endif // WITH_INT
36-
fabric_md.bridged.base.gtpu_presence = GtpuPresence.NONE;
36+
fabric_md.bridged.base.encap_presence = EncapPresence.NONE;
3737
transition check_ethernet;
3838
}
3939

@@ -195,6 +195,7 @@ parser FabricIngressParser (packet_in packet,
195195
gtpu_t gtpu = packet.lookahead<gtpu_t>();
196196
transition select(hdr.udp.dport, gtpu.version, gtpu.msgtype) {
197197
(GTPU_UDP_PORT, GTP_V1, GTPU_GPDU): parse_gtpu;
198+
(VXLAN_UDP_PORT, _, _): parse_vxlan;
198199
// Treat GTP control traffic as payload.
199200
default: accept;
200201
}
@@ -214,7 +215,7 @@ parser FabricIngressParser (packet_in packet,
214215
}
215216

216217
state set_gtpu_only {
217-
fabric_md.bridged.base.gtpu_presence = GtpuPresence.GTPU_ONLY;
218+
fabric_md.bridged.base.encap_presence = EncapPresence.GTPU_ONLY;
218219
transition parse_inner_ipv4;
219220
}
220221

@@ -229,13 +230,28 @@ parser FabricIngressParser (packet_in packet,
229230

230231
state parse_gtpu_ext_psc {
231232
packet.extract(hdr.gtpu_ext_psc);
232-
fabric_md.bridged.base.gtpu_presence = GtpuPresence.GTPU_WITH_PSC;
233+
fabric_md.bridged.base.encap_presence = EncapPresence.GTPU_WITH_PSC;
233234
transition select(hdr.gtpu_ext_psc.next_ext) {
234235
GTPU_NEXT_EXT_NONE: parse_inner_ipv4;
235236
default: accept;
236237
}
237238
}
238239

240+
state parse_vxlan {
241+
packet.extract(hdr.vxlan);
242+
fabric_md.bridged.base.encap_presence = EncapPresence.VXLAN;
243+
transition parse_inner_ethernet;
244+
}
245+
246+
state parse_inner_ethernet {
247+
packet.extract(hdr.inner_ethernet);
248+
packet.extract(hdr.inner_eth_type);
249+
transition select(hdr.inner_eth_type.value) {
250+
ETHERTYPE_IPV4: parse_inner_ipv4;
251+
default: accept;
252+
}
253+
}
254+
239255
state parse_inner_ipv4 {
240256
packet.extract(hdr.inner_ipv4);
241257
inner_ipv4_checksum.add(hdr.inner_ipv4);
@@ -315,6 +331,9 @@ control FabricIngressDeparser(packet_out packet,
315331
packet.emit(hdr.gtpu);
316332
packet.emit(hdr.gtpu_options);
317333
packet.emit(hdr.gtpu_ext_psc);
334+
packet.emit(hdr.vxlan);
335+
packet.emit(hdr.inner_ethernet);
336+
packet.emit(hdr.inner_eth_type);
318337
packet.emit(hdr.inner_ipv4);
319338
packet.emit(hdr.inner_tcp);
320339
packet.emit(hdr.inner_udp);
@@ -394,7 +413,7 @@ parser FabricEgressParser (packet_in packet,
394413
hdr.outer_gtpu_ext_psc.next_ext = GTPU_NEXT_EXT_NONE;
395414
#endif // WITH_SPGW
396415
#ifdef WITH_INT
397-
fabric_md.int_report_md.gtpu_presence = fabric_md.bridged.base.gtpu_presence;
416+
fabric_md.int_report_md.encap_presence = fabric_md.bridged.base.encap_presence;
398417
#endif // WITH_INT
399418
transition check_ethernet;
400419
}

ptf/tests/ptf/fabric.ptf/test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,7 +1891,7 @@ def runTest(self):
18911891
for send_report_to_spine in [False, True]:
18921892
if send_report_to_spine and tagged[1]:
18931893
continue
1894-
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
1894+
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
18951895
self.doRunTest(
18961896
vlan_conf,
18971897
tagged,
@@ -1966,7 +1966,7 @@ def runTest(self):
19661966
for send_report_to_spine in [False, True]:
19671967
if send_report_to_spine and tagged[1]:
19681968
continue
1969-
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
1969+
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
19701970
self.doRunTest(
19711971
vlan_conf,
19721972
tagged,
@@ -2037,7 +2037,7 @@ def runTest(self):
20372037
for send_report_to_spine in [False, True]:
20382038
if send_report_to_spine and tagged[1]:
20392039
continue
2040-
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
2040+
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
20412041
self.doRunTest(
20422042
vlan_conf,
20432043
tagged,
@@ -2078,7 +2078,7 @@ def doRunTest(
20782078

20792079
def runTest(self):
20802080
print("")
2081-
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
2081+
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
20822082
expect_int_report = True
20832083
# Change the IP destination to ensure we are using differnt
20842084
# flow for diffrent test cases since the flow report filter
@@ -2199,7 +2199,7 @@ def doRunTest(
21992199

22002200
def runTest(self):
22012201
print("")
2202-
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
2202+
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
22032203
expect_int_report = True
22042204
# Change the IP destination to ensure we are using differnt
22052205
# flow for diffrent test cases since the flow report filter

0 commit comments

Comments
 (0)