/* * 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 #define GENEVE_PORT 6082 header geneve_t { bit<2> ver; bit<6> opt_len; bit<1> o; bit<1> c; bit<6> reserved1; bit<16> protocol_type; bit<24> vni; bit<8> reserved2; }; // Struct so it can be a field within other headers struct geneve_option_t { bit<24> option_class_type; bit<3> reserved; bit<5> length; }; // Intermediate nodes (INT Transit Hops) must process this type of INT Header. header geneve_option_int_md_t { geneve_option_t base; bit<4> version; bit<1> discard; bit<1> exceeded_max_hops; bit<1> mtu_exceeded; bit<12> reserved; bit<5> hop_ml; bit<8> remaining_hop_count; bit<16> instruction_bitmap; bit<16> ds_id; bit<16> ds_instruction; bit<16> ds_flags; }; // Destination headers can be used to enable Edge-to-Edge communication between // the INT Source and INT Sink. header geneve_option_int_destination_t { geneve_option_t base; // Destination headers must only be consumed by the INT Sink }; // Intermediate nodes (INT Transit Hops) must process this type of INT Header // and generate reports to the monitoring system as instructed. header geneve_option_int_mx_t { geneve_option_t base; bit<4> version; bit<1> discard; bit<27> reserved1; bit<16> instruction_bitmap; bit<16> ds_id; bit<16> ds_instruction; bit<16> ds_flags; }; struct app_headers { NV_FIXED_HEADERS geneve_t custom_geneve; // geneve_option_t is not explicitly used by the P4 program, so a reference // placed in the headers the type is not optimized out. The NvOptionParser // instantiation references this type it by string name. geneve_option_t geneve_opt; geneve_option_int_md_t geneve_opt_int_md; geneve_option_int_destination_t geneve_opt_int_destination; geneve_option_int_mx_t geneve_opt_int_mx; }; parser geneve_parser( packet_in packet, out app_headers headers ) { NvOptionParser, _>( "opt_len", // options_length_field 2, // options_length_shift 0, // options_length_add "geneve_option_t", // option_layout_header_type "length", // option_length_field 2, // option_length_shift 4, // option_length_add "option_class_type", // option_type_field (list, _>>){ // options {24w0x010301, "headers.geneve_opt_int_md"}, {24w0x010302, "headers.geneve_opt_int_destination"}, {24w0x010303, "headers.geneve_opt_int_mx"} } ) geneveOptions; NV_FIXED_PARSER(packet, headers) @nv_transition_from("nv_parse_udp", GENEVE_PORT) state parse_geneve { // Fixed geneve is only an example; “base” header must be flex. packet.extract(headers.custom_geneve); geneveOptions.parseOptions(packet, headers); transition select(headers.custom_geneve.protocol_type) { NV_TYPE_IPV4 : nv_parse_inner_ipv4; NV_TYPE_IPV6 : nv_parse_inner_ipv6; NV_TYPE_MAC : nv_parse_inner_ethernet; default : accept; } } } control int_over_geneve( inout app_headers headers, in nv_standard_metadata_t std_meta, inout nv_empty_metadata_t user_meta, inout nv_empty_metadata_t pkt_out_meta ) { action forward(bit<32> port) { nv_send_to_port(port); } action drop() { nv_drop(); } table geneve_option_int_md_table { key = { headers.geneve_opt_int_md.ds_id : exact; } actions = { forward; NoAction; } default_action = NoAction(); const entries = { (16w0x100) : forward(1); } } table geneve_option_int_destination_table { key = { headers.custom_geneve.vni : exact; } actions = { forward; NoAction; } default_action = NoAction(); const entries = { (24w0x200) : forward(2); } } table geneve_option_int_mx_table { key = { headers.geneve_opt_int_mx.ds_id : exact; } actions = { forward; NoAction; } default_action = NoAction(); const entries = { (16w0x300) : forward(3); } } apply { if (headers.custom_geneve.isValid()) { geneve_option_int_md_table.apply(); geneve_option_int_destination_table.apply(); geneve_option_int_mx_table.apply(); } drop(); } } NvDocaPipeline( geneve_parser(), int_over_geneve() ) main;