/* * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: LicenseRef-NvidiaProprietary * * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual * property and proprietary rights in and to this material, related * documentation and any modifications thereto. Any use, reproduction, * disclosure or distribution of this material and related documentation * without an express license agreement from NVIDIA CORPORATION or * its affiliates is strictly prohibited. */ #include #include #include #include /* * This sample performs GTP matching using flex parser. * The GTP Tunnel Endpoint Identifier is used to selectively * forward the packets. */ const bit<32> WIRE_PORT = 32w00; const bit<32> GTP_VPORT = 32w01; const bit<32> DEFAULT_VPORT = 32w04; struct metadata_t { } #define GTP_U_PORT 2152 header Gtp_v1_h { bit<3> version; /** For GTPv1, this has a value of 1. */ bit protocol_type; /** GTP (value 1) from GTP' (value 0) */ bit reserved; bit extension_header_flag; /** extension header optional field. */ bit seq_number_flag; /** Sequence Number optional field */ bit n_pdu_number_flag; /** N-PDU number optional field */ bit<8> message_type; /** types of messages are defined in 3GPP TS 29.060 section 7.1 */ bit<16> message_length; /** length of the payload in bytes */ bit<32> teid; /** Tunnel endpoint identifier */ bit<16> sequence_number; /** optional */ bit<8> n_pdu_number; /** optional */ bit<8> next_extension_hdr_type; /** optional if any of the E, S, or PN bits are on. The field must be interpreted only if the E bit is on */ } struct headers_t { NV_FIXED_HEADERS Gtp_v1_h gtpv1; } parser packet_parser(packet_in packet, out headers_t headers) { NV_FIXED_PARSER(packet, headers) @nv_transition_from("nv_parse_udp", GTP_U_PORT) state parse_gtp { packet.extract(headers.gtpv1); transition accept; } } /** * This control admits GTP packets only if the tunnel ID matches * */ control gtp_tunnel( inout headers_t headers, in nv_standard_metadata_t std_meta, inout metadata_t user_meta, inout nv_empty_metadata_t pkt_out_meta ) { NvDirectCounter(NvCounterType.PACKETS_AND_BYTES) gtp_counter; action drop() { nv_drop(); } action send_to_port_gtp_table(nv_logical_port_t port) { gtp_counter.count(); nv_send_to_port(port); } action drop_gtp_table() { gtp_counter.count(); nv_drop(); } table gtp_table { key = { std_meta.ingress_port: exact; headers.gtpv1.teid: exact; } actions = { send_to_port_gtp_table; drop_gtp_table; } default_action = drop_gtp_table; direct_counter = gtp_counter; const entries = { (WIRE_PORT, 0x000000001) : send_to_port_gtp_table(GTP_VPORT); (GTP_VPORT, 0x000000001) : send_to_port_gtp_table(WIRE_PORT); } } apply { if (headers.gtpv1.isValid()) { if (gtp_table.apply().miss) { nv_send_to_port(DEFAULT_VPORT); } } drop(); } } NvDocaPipeline( packet_parser(), gtp_tunnel() ) main;