Skip to content

Commit

Permalink
[SDFAB-192] Report VXLAN-encaped packets to support end-host INT (#275)
Browse files Browse the repository at this point in the history
* Report VXLAN-encaped packets

* Add VXLAN pkt types for the INT-related PTF tests
  • Loading branch information
Tomasz Osiński authored Jun 18, 2021
1 parent 47c9c6b commit bcbb0e7
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 30 deletions.
2 changes: 1 addition & 1 deletion p4src/include/control/int.p4
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ control IntEgress (
fabric_md.int_report_md.eg_tstamp = eg_prsr_md.global_tstamp[31:0];
fabric_md.int_report_md.ip_eth_type = fabric_md.bridged.base.ip_eth_type;
fabric_md.int_report_md.flow_hash = fabric_md.bridged.base.inner_hash;
// fabric_md.int_report_md.gtpu_presence set by the parser
// fabric_md.int_report_md.encap_presence set by the parser
}

@hidden
Expand Down
29 changes: 20 additions & 9 deletions p4src/include/control/int_parser.p4
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ parser IntReportParser (packet_in packet,
fabric_md.int_report_md.ip_eth_type = ETHERTYPE_IPV4;
fabric_md.int_report_md.report_type = IntReportType_t.DROP;
fabric_md.int_report_md.mirror_type = FabricMirrorType_t.INVALID;
fabric_md.int_report_md.gtpu_presence = fabric_md.bridged.base.gtpu_presence;
fabric_md.int_report_md.encap_presence = fabric_md.bridged.base.encap_presence;
fabric_md.int_report_md.flow_hash = fabric_md.bridged.base.inner_hash;

/** report_fixed_header **/
Expand Down Expand Up @@ -174,11 +174,12 @@ parser IntReportParser (packet_in packet,

state check_eth_type {
packet.extract(hdr.eth_type);
transition select(hdr.eth_type.value, fabric_md.int_report_md.gtpu_presence) {
transition select(hdr.eth_type.value, fabric_md.int_report_md.encap_presence) {
(ETHERTYPE_MPLS, _): strip_mpls;
(ETHERTYPE_IPV4, GtpuPresence.NONE): handle_ipv4;
(ETHERTYPE_IPV4, GtpuPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
(ETHERTYPE_IPV4, GtpuPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
(ETHERTYPE_IPV4, EncapPresence.NONE): handle_ipv4;
(ETHERTYPE_IPV4, EncapPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
(ETHERTYPE_IPV4, EncapPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
(ETHERTYPE_IPV4, EncapPresence.VXLAN): strip_ipv4_udp_vxlan;
default: reject;
}
}
Expand All @@ -188,10 +189,11 @@ parser IntReportParser (packet_in packet,
state strip_mpls {
packet.advance(MPLS_HDR_BYTES * 8);
bit<IP_VER_BITS> ip_ver = packet.lookahead<bit<IP_VER_BITS>>();
transition select(ip_ver, fabric_md.int_report_md.gtpu_presence) {
(IP_VERSION_4, GtpuPresence.NONE): handle_ipv4;
(IP_VERSION_4, GtpuPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
(IP_VERSION_4, GtpuPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
transition select(ip_ver, fabric_md.int_report_md.encap_presence) {
(IP_VERSION_4, EncapPresence.NONE): handle_ipv4;
(IP_VERSION_4, EncapPresence.GTPU_ONLY): strip_ipv4_udp_gtpu;
(IP_VERSION_4, EncapPresence.GTPU_WITH_PSC): strip_ipv4_udp_gtpu_psc;
(IP_VERSION_4, EncapPresence.VXLAN): strip_ipv4_udp_vxlan;
default: reject;
}
}
Expand All @@ -207,6 +209,15 @@ parser IntReportParser (packet_in packet,
transition handle_ipv4;
}

state strip_ipv4_udp_vxlan {
packet.advance((IPV4_HDR_BYTES + UDP_HDR_BYTES + VXLAN_HDR_BYTES) * 8);
// Skip the Ethernet header.
// It will be removed from a packet and the outer Ethernet will be used
// as the inner Ethernet header.
packet.advance((ETH_HDR_BYTES) * 8);
transition handle_ipv4;
}

state handle_ipv4 {
// Extract only the length, required later to compute the lenght of the
// report encap headers.
Expand Down
8 changes: 4 additions & 4 deletions p4src/include/control/spgw.p4
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ control DecapGtpu(inout ingress_headers_t hdr,
hdr.gtpu.setInvalid();
hdr.gtpu_options.setInvalid();
hdr.gtpu_ext_psc.setInvalid();
fabric_md.bridged.base.gtpu_presence = GtpuPresence.NONE;
fabric_md.bridged.base.encap_presence = EncapPresence.NONE;
}
@hidden
action decap_inner_tcp() {
Expand Down Expand Up @@ -348,7 +348,7 @@ control SpgwIngress(
}
// PDRs
if (fabric_md.spgw.src_iface == SpgwInterface.ACCESS &&
fabric_md.bridged.base.gtpu_presence != GtpuPresence.NONE) {
fabric_md.bridged.base.encap_presence != EncapPresence.NONE) {
uplink_pdrs.apply();
} else if (fabric_md.spgw.src_iface == SpgwInterface.CORE ||
fabric_md.spgw.src_iface == SpgwInterface.FROM_DBUF) {
Expand Down Expand Up @@ -410,7 +410,7 @@ control SpgwEgress(
hdr.outer_gtpu.msglen = hdr.ipv4.total_len;
hdr.outer_gtpu.ex_flag = 0;
#ifdef WITH_INT
fabric_md.int_report_md.gtpu_presence = GtpuPresence.GTPU_ONLY;
fabric_md.int_report_md.encap_presence = EncapPresence.GTPU_ONLY;
#endif // WITH_INT
}

Expand All @@ -432,7 +432,7 @@ control SpgwEgress(
hdr.outer_gtpu_ext_psc.setValid();
hdr.outer_gtpu_ext_psc.qfi = qfi;
#ifdef WITH_INT
fabric_md.int_report_md.gtpu_presence = GtpuPresence.GTPU_WITH_PSC;
fabric_md.int_report_md.encap_presence = EncapPresence.GTPU_WITH_PSC;
#endif // WITH_INT
}

Expand Down
12 changes: 10 additions & 2 deletions p4src/include/define.p4
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define GTPU_EXT_PSC_HDR_BYTES 4
#define MPLS_HDR_BYTES 4
#define VLAN_HDR_BYTES 4
#define VXLAN_HDR_BYTES 8

#define PKT_INSTANCE_TYPE_NORMAL 0
#define PKT_INSTANCE_TYPE_INGRESS_CLONE 1
Expand Down Expand Up @@ -61,10 +62,15 @@ enum bit<8> SpgwInterface {
FROM_DBUF = 0x3
}

enum bit<2> GtpuPresence {
// According to our design choice, we report only the inner headers to the INT collector.
// The EncapPresence keeps track of the encapsulation protocol in use.
// The EncapPresence is further needed by the egress INT parser to strip out the outer encapsulation headers
// and put only inner headers in an INT report.
enum bit<2> EncapPresence {
NONE = 0x0,
GTPU_ONLY = 0x1,
GTPU_WITH_PSC = 0x2
GTPU_WITH_PSC = 0x2,
VXLAN = 0x3
}

const bit<16> GTPU_UDP_PORT = 2152;
Expand Down Expand Up @@ -131,6 +137,8 @@ const vlan_id_t DEFAULT_VLAN_ID = 12w4094;
const bit<8> DEFAULT_MPLS_TTL = 64;
const bit<8> DEFAULT_IPV4_TTL = 64;

const bit<16> VXLAN_UDP_PORT = 4789;

// The recirculation port uses the same number for all HW pipes. The actual port
// ID (DP_ID) can be obtained by prefixing the HW pipe ID (2 bits).
const bit<7> RECIRC_PORT_NUMBER = 7w68;
Expand Down
15 changes: 12 additions & 3 deletions p4src/include/header.p4
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ header icmp_t {
// Other optional fields...
}

header vxlan_t {
bit<8> flags;
bit<24> reserved;
bit<24> vni;
bit<8> reserved_2;
}

// GTPU v1 -- 3GPP TS 29.281 version 15.7.0
// https://www.etsi.org/deliver/etsi_ts/129200_129299/129281/15.07.00_60/ts_129281v150700p.pdf
Expand Down Expand Up @@ -234,7 +240,7 @@ header local_report_header_t {
@pa_no_overlay("egress", "fabric_md.int_report_md.ip_eth_type")
@pa_no_overlay("egress", "fabric_md.int_report_md.report_type")
@pa_no_overlay("egress", "fabric_md.int_report_md.flow_hash")
@pa_no_overlay("egress", "fabric_md.int_report_md.gtpu_presence")
@pa_no_overlay("egress", "fabric_md.int_report_md.encap_presence")
header int_report_metadata_t {
BridgedMdType_t bmd_type;
@padding bit<5> _pad0;
Expand All @@ -252,7 +258,7 @@ header int_report_metadata_t {
bit<8> drop_reason;
bit<16> ip_eth_type;
@padding bit<6> _pad5;
GtpuPresence gtpu_presence;
EncapPresence encap_presence;
@padding bit<6> _pad6;
IntReportType_t report_type;
flow_hash_t flow_hash;
Expand Down Expand Up @@ -280,7 +286,7 @@ struct bridged_metadata_base_t {
bool is_multicast;
fwd_type_t fwd_type;
vlan_id_t vlan_id;
GtpuPresence gtpu_presence;
EncapPresence encap_presence;
// bit<3> vlan_pri;
// bit<1> vlan_cfi;
bit<8> mpls_ttl;
Expand Down Expand Up @@ -414,6 +420,9 @@ struct ingress_headers_t {
gtpu_t gtpu;
gtpu_options_t gtpu_options;
gtpu_ext_psc_t gtpu_ext_psc;
vxlan_t vxlan;
ethernet_t inner_ethernet;
eth_type_t inner_eth_type;
ipv4_t inner_ipv4;
tcp_t inner_tcp;
udp_t inner_udp;
Expand Down
27 changes: 23 additions & 4 deletions p4src/include/parser.p4
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ parser FabricIngressParser (packet_in packet,
#ifdef WITH_INT
fabric_md.bridged.int_bmd.drop_reason = IntDropReason_t.DROP_REASON_UNKNOWN;
#endif // WITH_INT
fabric_md.bridged.base.gtpu_presence = GtpuPresence.NONE;
fabric_md.bridged.base.encap_presence = EncapPresence.NONE;
transition check_ethernet;
}

Expand Down Expand Up @@ -195,6 +195,7 @@ parser FabricIngressParser (packet_in packet,
gtpu_t gtpu = packet.lookahead<gtpu_t>();
transition select(hdr.udp.dport, gtpu.version, gtpu.msgtype) {
(GTPU_UDP_PORT, GTP_V1, GTPU_GPDU): parse_gtpu;
(VXLAN_UDP_PORT, _, _): parse_vxlan;
// Treat GTP control traffic as payload.
default: accept;
}
Expand All @@ -214,7 +215,7 @@ parser FabricIngressParser (packet_in packet,
}

state set_gtpu_only {
fabric_md.bridged.base.gtpu_presence = GtpuPresence.GTPU_ONLY;
fabric_md.bridged.base.encap_presence = EncapPresence.GTPU_ONLY;
transition parse_inner_ipv4;
}

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

state parse_gtpu_ext_psc {
packet.extract(hdr.gtpu_ext_psc);
fabric_md.bridged.base.gtpu_presence = GtpuPresence.GTPU_WITH_PSC;
fabric_md.bridged.base.encap_presence = EncapPresence.GTPU_WITH_PSC;
transition select(hdr.gtpu_ext_psc.next_ext) {
GTPU_NEXT_EXT_NONE: parse_inner_ipv4;
default: accept;
}
}

state parse_vxlan {
packet.extract(hdr.vxlan);
fabric_md.bridged.base.encap_presence = EncapPresence.VXLAN;
transition parse_inner_ethernet;
}

state parse_inner_ethernet {
packet.extract(hdr.inner_ethernet);
packet.extract(hdr.inner_eth_type);
transition select(hdr.inner_eth_type.value) {
ETHERTYPE_IPV4: parse_inner_ipv4;
default: accept;
}
}

state parse_inner_ipv4 {
packet.extract(hdr.inner_ipv4);
inner_ipv4_checksum.add(hdr.inner_ipv4);
Expand Down Expand Up @@ -315,6 +331,9 @@ control FabricIngressDeparser(packet_out packet,
packet.emit(hdr.gtpu);
packet.emit(hdr.gtpu_options);
packet.emit(hdr.gtpu_ext_psc);
packet.emit(hdr.vxlan);
packet.emit(hdr.inner_ethernet);
packet.emit(hdr.inner_eth_type);
packet.emit(hdr.inner_ipv4);
packet.emit(hdr.inner_tcp);
packet.emit(hdr.inner_udp);
Expand Down Expand Up @@ -394,7 +413,7 @@ parser FabricEgressParser (packet_in packet,
hdr.outer_gtpu_ext_psc.next_ext = GTPU_NEXT_EXT_NONE;
#endif // WITH_SPGW
#ifdef WITH_INT
fabric_md.int_report_md.gtpu_presence = fabric_md.bridged.base.gtpu_presence;
fabric_md.int_report_md.encap_presence = fabric_md.bridged.base.encap_presence;
#endif // WITH_INT
transition check_ethernet;
}
Expand Down
10 changes: 5 additions & 5 deletions ptf/tests/ptf/fabric.ptf/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1891,7 +1891,7 @@ def runTest(self):
for send_report_to_spine in [False, True]:
if send_report_to_spine and tagged[1]:
continue
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
self.doRunTest(
vlan_conf,
tagged,
Expand Down Expand Up @@ -1966,7 +1966,7 @@ def runTest(self):
for send_report_to_spine in [False, True]:
if send_report_to_spine and tagged[1]:
continue
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
self.doRunTest(
vlan_conf,
tagged,
Expand Down Expand Up @@ -2037,7 +2037,7 @@ def runTest(self):
for send_report_to_spine in [False, True]:
if send_report_to_spine and tagged[1]:
continue
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
self.doRunTest(
vlan_conf,
tagged,
Expand Down Expand Up @@ -2078,7 +2078,7 @@ def doRunTest(

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

def runTest(self):
print("")
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES:
for pkt_type in BASE_PKT_TYPES | GTP_PKT_TYPES | VXLAN_PKT_TYPES:
expect_int_report = True
# Change the IP destination to ensure we are using differnt
# flow for diffrent test cases since the flow report filter
Expand Down
Loading

0 comments on commit bcbb0e7

Please sign in to comment.