From 4e2651f220226b534ee06bf5186668ace8071bbf Mon Sep 17 00:00:00 2001 From: Marco Hofstetter Date: Wed, 18 Dec 2024 20:30:32 +0100 Subject: [PATCH] bpf_metadata: introduce udp bpf_metadata factory & instance Signed-off-by: Marco Hofstetter --- cilium/bpf_metadata.cc | 64 ++++++++++++++++++++++++++++++++++++++++-- cilium/bpf_metadata.h | 19 +++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/cilium/bpf_metadata.cc b/cilium/bpf_metadata.cc index 7659e9dab..f274b3cae 100644 --- a/cilium/bpf_metadata.cc +++ b/cilium/bpf_metadata.cc @@ -5,6 +5,7 @@ #include +#include "envoy/api/io_error.h" #include "envoy/network/listen_socket.h" #include "envoy/registry/registry.h" #include "envoy/singleton/manager.h" @@ -35,15 +36,18 @@ class BpfMetadataConfigFactory : public NamedListenerFilterConfigFactory { const Protobuf::Message& proto_config, const Network::ListenerFilterMatcherSharedPtr& listener_filter_matcher, Configuration::ListenerFactoryContext& context) override { + auto config = std::make_shared( MessageUtil::downcastAndValidate( proto_config, context.messageValidationVisitor()), context); + // Set the socket mark option for the listen socket. // Can use identity 0 on the listen socket option, as the bpf datapath is only interested // in whether the proxy is ingress, egress, or if there is no proxy at all. std::shared_ptr options = std::make_shared(); + uint32_t mark = (config->is_ingress_) ? 0x0A00 : 0x0B00; options->push_back(std::make_shared(mark, 0)); context.addListenSocketOptions(options); @@ -69,6 +73,52 @@ class BpfMetadataConfigFactory : public NamedListenerFilterConfigFactory { REGISTER_FACTORY(BpfMetadataConfigFactory, NamedListenerFilterConfigFactory){FACTORY_VERSION(1, 1, 0, {{}})}; +/** + * Config registration for the UDP bpf metadata filter. @see + * NamedUdpListenerFilterConfigFactory. + */ +class UdpBpfMetadataConfigFactory : public NamedUdpListenerFilterConfigFactory { +public: + // NamedUdpListenerFilterConfigFactory + Network::UdpListenerFilterFactoryCb + createFilterFactoryFromProto(const Protobuf::Message& proto_config, + Configuration::ListenerFactoryContext& context) override { + + auto config = std::make_shared( + MessageUtil::downcastAndValidate( + proto_config, context.messageValidationVisitor()), + context); + + // Set the socket mark option for the listen socket. + // Can use identity 0 on the listen socket option, as the bpf datapath is only interested + // in whether the proxy is ingress, egress, or if there is no proxy at all. + std::shared_ptr options = + std::make_shared(); + + uint32_t mark = (config->is_ingress_) ? 0x0A00 : 0x0B00; + options->push_back(std::make_shared(mark, 0)); + context.addListenSocketOptions(options); + + return [config](Network::UdpListenerFilterManager& udp_listener_filter_manager, + Network::UdpReadFilterCallbacks& callbacks) mutable -> void { + udp_listener_filter_manager.addReadFilter( + std::make_unique(config, callbacks)); + }; + } + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique<::cilium::BpfMetadata>(); + } + + std::string name() const override { return "cilium.bpf_metadata"; } +}; + +/** + * Static registration for the UDP bpf metadata filter. @see RegisterFactory. + */ +REGISTER_FACTORY(UdpBpfMetadataConfigFactory, + NamedUdpListenerFilterConfigFactory){FACTORY_VERSION(1, 1, 0, {{}})}; + } // namespace Configuration } // namespace Server @@ -118,6 +168,7 @@ Config::Config(const ::cilium::BpfMetadata& config, Network::Utility::parseInternetAddressNoThrow(config.ipv6_source_address())), enforce_policy_on_l7lb_(config.enforce_policy_on_l7lb()), policy_update_warning_limit_ms_(std::chrono::milliseconds(100)) { + const uint64_t limit = DurationUtil::durationToMilliseconds(config.policy_update_warning_limit()); if (limit > 0) { policy_update_warning_limit_ms_ = std::chrono::milliseconds(limit); @@ -479,9 +530,7 @@ Network::FilterStatus Instance::onAccept(Network::ListenerFilterCallbacks& cb) { } // Set socket options for linger and keepalive (5 minutes). - struct ::linger lin { - true, 10 - }; + struct ::linger lin{true, 10}; int keepalive = true; int secs = 5 * 60; // Five minutes @@ -517,6 +566,15 @@ Network::FilterStatus Instance::onData(Network::ListenerFilterBuffer&) { size_t Instance::maxReadBytes() const { return 0; } +Network::FilterStatus UdpInstance::onData([[maybe_unused]] Network::UdpRecvData& data) { + return Network::FilterStatus::Continue; +} + +Network::FilterStatus +UdpInstance::onReceiveError([[maybe_unused]] Api::IoError::IoErrorCode error_code) { + return Network::FilterStatus::Continue; +} + } // namespace BpfMetadata } // namespace Cilium } // namespace Envoy diff --git a/cilium/bpf_metadata.h b/cilium/bpf_metadata.h index 9c4c5c8cf..d2d80d180 100644 --- a/cilium/bpf_metadata.h +++ b/cilium/bpf_metadata.h @@ -1,5 +1,6 @@ #pragma once +#include "envoy/api/io_error.h" #include "envoy/json/json_object.h" #include "envoy/network/filter.h" #include "envoy/server/filter_config.h" @@ -84,6 +85,24 @@ class Instance : public Network::ListenerFilter, Logger::Loggable { +public: + UdpInstance(const ConfigSharedPtr& config, Network::UdpReadFilterCallbacks& callbacks) + : UdpListenerReadFilter(callbacks), config_(config) {} + + // Network::UdpListenerReadFilter + Network::FilterStatus onData(Network::UdpRecvData& data) override; + + // Network::UdpListenerReadFilter + Network::FilterStatus onReceiveError(Api::IoError::IoErrorCode error_code) override; + +private: + const ConfigSharedPtr config_; +}; + } // namespace BpfMetadata } // namespace Cilium } // namespace Envoy