Skip to content

http/transport tap: Add a new UDP sink#37172

Merged
wbpcode merged 11 commits intoenvoyproxy:mainfrom
coolg92003:main
Jan 16, 2025
Merged

http/transport tap: Add a new UDP sink#37172
wbpcode merged 11 commits intoenvoyproxy:mainfrom
coolg92003:main

Conversation

@coolg92003
Copy link
Copy Markdown
Contributor

Commit Message:
Add an UDP sink for HTTP/Transport Tap
Additional Description:
See more detailed information in issue #36945
Risk Level: low
Testing:
Manual test has been done
Also CPR test is done
see issue 36945 for more information

Docs Changes:
Build is passed
Release Notes:
Platform Specific Features: N/A
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]

@repokitteh-read-only
Copy link
Copy Markdown

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to (api/envoy/|docs/root/api-docs/).
envoyproxy/api-shepherds assignee is @adisuissa
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #37172 was opened by coolg92003.

see: more, trace.

Copy link
Copy Markdown
Contributor

@adisuissa adisuissa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this!
I've looked at the PR description and the issue, but couldn't find an answer: why a custom_sink (see a test example) cannot be used?

cc @mattklein123 @xu1zhou as TAP filter code owners.

@coolg92003
Copy link
Copy Markdown
Contributor Author

Thanks for working on this! I've looked at the PR description and the issue, but couldn't find an answer: why a custom_sink (see a test example) cannot be used?

cc @mattklein123 @xu1zhou as TAP filter code owners.
Hi @adisuissa,
It is no use to read that example, if you check #28838, then you can know that, until now, no one except the owner know how to use that sink :).

thanks
Cliff

@adisuissa
Copy link
Copy Markdown
Contributor

Hi @adisuissa,
It is no use to read that example, if you check #28838, then you can know that, until now, no one except the owner know how to use that sink :).

thanks Cliff

Then it probably should be fixed, instead of adding a new field.
Can you provide more details on what is the issue with the current custom-sink?

@coolg92003
Copy link
Copy Markdown
Contributor Author

hi @adisuissa ,

Can you provide more details on what is the issue with the current custom-sink?
The key is that it doesn't know how to configure the custom_sink,
I have tried several extension types, but it doesn't work. see below for one try

                  "sinks": [
                   {
                    "format": "JSON_BODY_AS_STRING",
                    "custom_sink": {
                     "name": "random_name",
                     "typed_config": {
                      "@type": "type.googleapis.com/xds.type.v3.TypedStruct",
                      "type_url": "type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig",
                      "value": {
                       "sub_clusters_config": {
                        "preresolve_clusters": [
                         {
                          "protocol": "UDP",
                          "address": "127.0.0.1",
                          "port_value": 8080
                         }
                        ]
                       }
                      }
                     }
                    }
                   }
                  ],

you can see issue #28838, the owner doesn't give an example on how to use this sink.
that is why I want to give the other sink to improve the tap performance.
thanks
Cliff

@adisuissa
Copy link
Copy Markdown
Contributor

hi @adisuissa ,

Can you provide more details on what is the issue with the current custom-sink?
The key is that it doesn't know how to configure the custom_sink,
I have tried several extension types, but it doesn't work. see below for one try

                  "sinks": [
                   {
                    "format": "JSON_BODY_AS_STRING",
                    "custom_sink": {
                     "name": "random_name",
                     "typed_config": {
                      "@type": "type.googleapis.com/xds.type.v3.TypedStruct",
                      "type_url": "type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig",
                      "value": {
                       "sub_clusters_config": {
                        "preresolve_clusters": [
                         {
                          "protocol": "UDP",
                          "address": "127.0.0.1",
                          "port_value": 8080
                         }
                        ]
                       }
                      }
                     }
                    }
                   }
                  ],

you can see issue #28838, the owner doesn't give an example on how to use this sink. that is why I want to give the other sink to improve the tap performance. thanks Cliff

I think the config should be similar to the following:

                  "sinks": [
                   {
                    "format": "JSON_BODY_AS_STRING",
                    "custom_sink": {
                     "name": "random_name",
                     "typed_config": {
                       "@type": "type.googleapis.com/envoy.extensions.tap_sinks.udp_sink.v3.UdpSink",
                       "udp_address": { ... }
                     }
                    }
                   }
                  ],

Or something of this structure.
The idea behind typed-configs is that one can have different types instantiated there. Then there can be a Sink interface that all the sinks implement, and the Envoy will instantiate the correct sink object there (using its config).

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @adisuissa,
Sorry not catch your meaning. from my thinking, after custom_sink, it should can use existing extension. but I and my workmate try several one types, it doesn't work.
that is why I write another one.

hi @ashishb-solo
Would you share your opinion?

thanks
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @fredyw
Seem the UT failed on ARM in case "TEST_F(GetAddrInfoDnsImplTest, NoName) ".
image

Would you help check it?
Check the link:https://github.com/envoyproxy/envoy/actions/runs/11945152238/job/33297333616
thanks
Cliff

@ashishb-90
Copy link
Copy Markdown
Contributor

Hi @coolg92003 my apologies for not being more responsive here, I have been very busy lately.

Adi's suggestion in this comment is spot-on. I would try changing your configuration to the one that he recommended and continue from there. If you can post the issues that you're experiencing when you try that, we may be able to help you and figure out how to fix it.

@adisuissa
Copy link
Copy Markdown
Contributor

I think a close example can be the stateful-session filter (api, config-cc. Similar to "tap" the stateful-session filter is a filter that can be added to the filter chain.
It has an additional sub-config (session_state) that can be configured with some extension.
The possible (sub) extensions are: cookie and header.

In your case the sub-extension will be the UDP sink.

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @ashishb-solo ,
Really appreciated your response! As you know current existed sink(file and admin) can't meet performance needs.

then I try your contribution about custom_sink, I assume that it doesn't need change any envoy code when using this sink, right???
Search available extensions from link(https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/config),
Try extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig, but
Got the blow error:

[2024-11-25 02:14:37.774][1406716][critical][main] [source/server/server.cc:413] error initializing config '  ./TapUdpenvoyStaticCustom.yaml': Didn't find a registered implementation for 'cfx_custom_sink' with type URL: 'envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig'

when configure as below:

                 output_config:
                    streaming: false
                    sinks:
                    - format: JSON_BODY_AS_STRING
                      custom_sink:
                        name: cfx_custom_sink
                        typed_config:
                          "@type": type.googleapis.com/xds.type.v3.TypedStruct
                          type_url: type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
                          value:
                            sub_clusters_config:
                              preresolve_clusters:
                                protocol: UDP
                                address: 127.0.0.1
                                port_value: 8080
                    max_buffered_rx_bytes: 1000000
                    max_buffered_tx_bytes: 1000000

Does this mean that there is no available extension for custom_sink because they don't implement TapSinkFactory as state in link (#28808)?
or would you show me an extension in link(https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/config)?
or it has to contribute an new extension? such as, UDP or TCP or GRPC or HTTP?
or would you write an simple example extension, then I can contribute based on your example?

Look forward to you!
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @adisuissa ,
Appreciated your suggestion! however, I think below doesn't meet vTap performance needs as below

It has an additional sub-config (session_state) that can be configured with some extension.
The possible (sub) extensions are: cookie and header.

Let's wait the answer from @ashishb-solo .
BTW, how to contact @fredyw? The UT has issue for ARM

thanks
Cliff

@ashishb-90
Copy link
Copy Markdown
Contributor

ashishb-90 commented Nov 25, 2024

Hi Cliff,

You are correct that custom_sink does not implement an extension, it only provides a point of entry for configuration that can implement a sink. In this case, you want to use custom_sink to configure the UDP sink extension that you are writing, so your @type should be type.googleapis.com/envoy.extensions.tap_sinks.udp_sink.v3.UdpSink, not type.googleapis.com/xds.type.v3.TypedStruct. Then the kCustomSink case statement (found here) will

  1. extract the configuration you defined and parse it into a protobuf::MessagePtr object,
  2. instantiate a sink factory (tap_sink_factory)
  3. call tap_sink_factory.createSinkPtr with the MessagePtr object that was parsed in step Initial import #1.

So what this means is that you have to take the following steps:

  1. Define a UdpSinkFactory object that inherits TapSinkFactory
  2. Implement UdpSinkFactory.createSinkPtr and have it return an instance of your UdpSink class
  3. Call REGISTER_FACTORY(UdpSinkFactory, TapSinkFactory) so Envoy knows that it can use your factory in the kCustomSink clause.

Hopefully I'm not missing any steps here, but I believe that is all that you have to do. Hope this helps,

-Ashish

@coolg92003
Copy link
Copy Markdown
Contributor Author

hi @ashishb-solo ,
Appreciated your detailed explanation! As you know, I have little developing experience on envoy.
I will study your suggestion and try again!
thanks
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

hi @mattklein123
Really need your Comments because you are the owner of tap!
Do you agree my current implement for a new UDP sink or
implement it as an UDP extension for tap Performance issue?

If you prefer to the UDP extension, then would you comment below my procedure?

As you know, I have little experience on envoy development, even little on extension.
From my current understanding based on help from @adisuissa and @ashishb-solo , to add an UDP extension:

  1. Add dir tap_sinks/udp_sinks/v3 under api/envoy/extensions
    then create BUILD and udp_sink.proto,

  2. change code as below suggestion as below

  • Define a UdpSinkFactory object that inherits TapSinkFactory
    
  • Implement UdpSinkFactory.createSinkPtr and have it return an instance of your UdpSink class
    
  • Call REGISTER_FACTORY(UdpSinkFactory, TapSinkFactory) so Envoy knows that it can use your factory in the kCustomSink clause.
    
  1. Configure new extension as below:
                  "sinks": [
                   {
                    "format": "JSON_BODY_AS_STRING",
                    "custom_sink": {
                     "name": "udp_sink",
                     "typed_config": {
                       "@type": "type.googleapis.com/envoy.extensions.tap_sinks.udp_sink.v3.UdpSink",
                       "udp_address": { ... }
                     }
                    }
                   }
                  ],

Look forward to you!

Thanks
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

/retest

3 similar comments
@coolg92003
Copy link
Copy Markdown
Contributor Author

/retest

@coolg92003
Copy link
Copy Markdown
Contributor Author

/retest

@coolg92003
Copy link
Copy Markdown
Contributor Author

/retest

@coolg92003
Copy link
Copy Markdown
Contributor Author

hi @ashishb-solo ,
During waiting @mattklein123's comment, I study your propose very hard and meet two questions need your suggestion:

  1. I needs modify the function createSinkPtr(), otherwise, it can't cast protobuf message to envoy::extensions::tap_sinks::udp_sink::v3::UDPSink
    Would you please check below code item 2 and share your idear?
  2. would check whether my "REGISTER_FACTORY(UdpTapSinkFactory, TapSinkFactory);" is correct at below code item 5?
    Best regards,
    Cliff

Code details as below:

  1. add udp_sink.proto under api/envoy/extensions/tap_sinks/udp_sink/v3
package envoy.extensions.tap_sinks.udp_sink.v3;

import "envoy/config/core/v3/address.proto";

import "udpa/annotations/status.proto";
import "validate/validate.proto";
import "udpa/annotations/versioning.proto";

option java_package = "io.envoyproxy.envoy.extensions.tap_sinks.udp_sink.v3";
option java_outer_classname = "UdpSinkProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/tap_sinks/udp_sink/v3;udp_sinkv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Udp sink configuration]
// Udp sink configuration.
message UDPSink {
  //   Configure UDP Address
  //   
  config.core.v3.SocketAddress udp_address = 1;
}
  1. change the base class TapSinkFactory to modify the creatSinkPtr in file source/extensions/common/tap/tap.h as below:
 * @param config supplies the protobuf configuration for the sink factory
    * @param cluster_manager is a ClusterManager from the HTTP/transport socket context
    */
-  virtual SinkPtr createSinkPtr(const Protobuf::Message& config, SinkContext context) PURE;
+  //virtual SinkPtr createSinkPtr(const Protobuf::Message& config, SinkContext context) PURE;
+  virtual SinkPtr createSinkPtr(const Protobuf::Message& config, Server::Configuration::TransportSocketFactoryContext& tsf_con
text) PURE;
+  virtual SinkPtr createSinkPtr(const Protobuf::Message& config, Server::Configuration::FactoryContext& http_context) PURE;
 };
  1. change file source/extensions/common/tap/tap_config_base.cc when creating custom sink
  case ProtoOutputSink::OutputSinkTypeCase::kCustomSink: {
@@ -115,6 +115,7 @@ TapConfigBaseImpl::TapConfigBaseImpl(const envoy::config::tap::v3::TapConfig& pr
       config = Config::Utility::translateAnyToFactoryConfig(sinks[0].custom_sink().typed_config(),
                                                             tsf_context.messageValidationVisitor(),
                                                             tap_sink_factory);
+      sink_ = tap_sink_factory.createSinkPtr(*config, tsf_context);
     } else {
       Server::Configuration::FactoryContext& http_context =
           absl::get<HttpContextRef>(context).get();
@@ -122,9 +123,9 @@ TapConfigBaseImpl::TapConfigBaseImpl(const envoy::config::tap::v3::TapConfig& pr
           sinks[0].custom_sink().typed_config(),
           http_context.serverFactoryContext().messageValidationContext().staticValidationVisitor(),
           tap_sink_factory);
+      sink_ = tap_sink_factory.createSinkPtr(*config, http_context);
     }
 
-    sink_ = tap_sink_factory.createSinkPtr(*config, context);
     sink_to_use_ = sink_.get();
     break;
  1. add new class in file source/extensions/common/tap/tap_config_base.h
+class UdpTapSinkFactory : public TapSinkFactory {
+public:
+  ~UdpTapSinkFactory() override = default;
+  std::string category() const override { return "envoy.tap.sinks.udp"; }
+  std::string name() const override { return "envoy.tap.sinks.udp"; }
+  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
+    return std::make_unique<envoy::extensions::tap_sinks::udp_sink::v3::UDPSink>();
+  }
+  /**
+   * Create a UDP Sink that can be used for writing out data produced by the tap filter.
+   * @param config supplies the protobuf configuration for the sink factory
+   * @param cluster_manager is a ClusterManager from the HTTP/transport socket context
+   */
+  //SinkPtr createSinkPtr(const Protobuf::Message& config, SinkContext context) override;
+  SinkPtr createSinkPtr(const Protobuf::Message& config, Server::Configuration::TransportSocketFactoryContext& tsf_context) ov
erride;
+  SinkPtr createSinkPtr(const Protobuf::Message& config, Server::Configuration::FactoryContext& http_context) override;
+};
  1. implement createSInkPtr() in file source/extensions/common/tap/tap_config_base.cc
+SinkPtr UdpTapSinkFactory::createSinkPtr(const Protobuf::Message& config, Server::Configuration::TransportSocketFactoryContext
& tsf_context) {
+  return std::make_unique<UdpTapSink>(MessageUtil::downcastAndValidate<const envoy::extensions::tap_sinks::udp_sink::v3::UDPSi
nk&>(config, tsf_context.messageValidationVisitor()));
+}More--
+
+SinkPtr UdpTapSinkFactory::createSinkPtr(const Protobuf::Message& config, Server::Configuration::FactoryContext& http_context)
 {
+  return std::make_unique<UdpTapSink>(MessageUtil::downcastAndValidate<const envoy::extensions::tap_sinks::udp_sink::v3::UDPSi
nk&>(config, http_context.serverFactoryContext().messageValidationContext().staticValidationVisitor()));
+}
+
+**REGISTER_FACTORY(UdpTapSinkFactory, TapSinkFactory);**

@ashishb-90
Copy link
Copy Markdown
Contributor

Great work Cliff!

I needs modify the function createSinkPtr(), otherwise, it can't cast protobuf message to envoy::extensions::tap_sinks::udp_sink::v3::UDPSink
Would you please check below code item 2 and share your idear?

I think that's a really nice change. The definition of SinkContext is very complicated, and I think your version is much simpler and cleaner. Just make sure to delete SinkContext as part of this pull request since it is probably not being used anywhere anymore.

would check whether my "REGISTER_FACTORY(UdpTapSinkFactory, TapSinkFactory);" is correct at below code item 5?

It looks fine to me. Does it compile? I would try configuring it using the static configuration that Adi linked above (with the "@type": "type.googleapis.com/envoy.extensions.tap_sinks.udp_sink.v3.UdpSink" typed_config) and see if UdpTapSinkFactory::createSinkPtr gets called. You could try putting a print statement in those functions to be completely sure.

Overall, your code looks very good to me. I think you're on the right track!

Best,

-Ashish

@coolg92003
Copy link
Copy Markdown
Contributor Author

/retest

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @adisuissa ,
Your comments give a log of confidence! :) Really appreciated!
I never add extension before, it seems needs lots of work than before.
Currently, I still study the link Add Extension API.
each time, when I run command "./tools/proto_format/proto_format.sh fix", then files (BUILD and udp_sink.proto) under /source/api/envoy/extensions/tap_sinks/udp_sink/v3 are gone.
I am still struggled on this.
Have a nice day!
Cliff

@adisuissa
Copy link
Copy Markdown
Contributor

Hi @adisuissa , Your comments give a log of confidence! :) Really appreciated! I never add extension before, it seems needs lots of work than before. Currently, I still study the link Add Extension API. each time, when I run command "./tools/proto_format/proto_format.sh fix", then files (BUILD and udp_sink.proto) under /source/api/envoy/extensions/tap_sinks/udp_sink/v3 are gone. I am still struggled on this. Have a nice day! Cliff

I'm not sure what is happening in your case, but looking at the link you provided I see the following:

  1. Run ./tools/proto_format/proto_format.sh fix. Before running the script, you will need to commit your local changes. By adding the commit, the tool will recognize the change, and will regenerate the BUILD file and reformat foobar.proto as needed. If you have not followed any of the above steps correctly proto_format.sh may remove some of the files that you added. If that is the case you can revert to the committed state, and try again once any issues are resolved.

Have you committed your local changes?

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @ashishb-solo
You are really great! your foresee is correct. Build is clean and Tap message can be sent out. I can share my test env if you needed.

Hi @adisuissa
About the configuration, you are correct.
After re-changing the code and test again both http tap and transport tap work by custom sink.

For now, how we do next?
use another PR to do UDP extension for customer sink or use this one? or
do we still need wait for Matt's comment

See below for static configuration file
http tap:
image

transport tap;
image

I will continue to do the test and refine the code.
Best regards,
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

coolg92003 commented Dec 9, 2024

Hi @ashishb-solo,
Would you help check CI and let me know anything missed?
Thanks again for your great custom sink!
Seems that UT has issue for polymorphic function createSinkPtr()
Can I change it to two functions, createHttpCtxSinkPtr() and CreateTransportCtxSinkPtr()?
Cliff

Copy link
Copy Markdown
Contributor

@adisuissa adisuissa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
In addition to the comments, I suggest adding an integration test to make sure this sink works as expected.

Comment thread CODEOWNERS Outdated
// [#protodoc-title: Udp sink configuration]
// [#extension: envoy.tap_sinks.udp_sink]

// Udp sink configuration.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding an example how to configure this sink.

Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.h Outdated
Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.h Outdated
Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.h Outdated
Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.cc
Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.cc Outdated
Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.cc Outdated
Comment thread source/extensions/tap_sinks/udp_sink/udp_sink_impl.cc
Comment thread test/extensions/common/tap/admin_test.cc Outdated
@wbpcode
Copy link
Copy Markdown
Member

wbpcode commented Dec 15, 2024

Thanks for the contribution. But similar to @adisuissa I do have no more bandwidth to sponsor a feature that I never concerned/used before.

I will suggest you to maintain this extension in your fork or your extensions repo (like istio/proxy, etc). If you don't want to maintain a fork, you can still move this extension to contrib which needn't additional sponsor. You can use a @unowned to complete your owner list first if no another one to support this feature.

@wbpcode
Copy link
Copy Markdown
Member

wbpcode commented Dec 15, 2024

/wait

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @wbpcode

Thanks for the contribution. But similar to @adisuissa I do have no more bandwidth to sponsor a feature that I never concerned/used before.
I will suggest you to maintain this extension in your fork or your extensions repo (like istio/proxy, etc). If you don't want to maintain a fork, you can still move this extension to contrib which needn't additional sponsor. You can use a https://github.com/unowned to complete your owner list first if no another one to support this feature.

Really appreciated your comments and suggestion!
I need talking with local team and needing more studying on what is the difference between extension and contrib.
From current checking, seems some built product doesn't include the code in contrib.
thanks
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

coolg92003 commented Dec 16, 2024

Hi @adisuissa,

Thanks!
In addition to the comments, I suggest adding an integration test to make sure this sink works as expected.

Sure, I can do that. this is complicated because there is no udp server there. I am still thinking...

one more question, except Matt and wbpcode, who else can sponsor this extension? code is very easy and it is configurable. Therefore, the risk is the lowest. From the senior owner in this link, who can be contacted?

The reason that I don't prefer to go contrib is that it doesn't match current design.
As you know, no matter http or transport tap, both have performance issues, and sometimes, envoy building product doesn't include contrib. There is no other option if user wants to debug traffic in TLS connection(especially TLS1.3).

At same time, let me study on how to write code in contrib.

thanks
Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

Seems that envoy has lots of limitation on time and thread and still thinking integration test case...

@coolg92003
Copy link
Copy Markdown
Contributor Author

/retest

Copy link
Copy Markdown
Contributor

@adisuissa adisuissa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

verifyStaticFilePerTap(fmt::format(filter_config, getTempPathPrefix()));
}

TEST_P(TapIntegrationTest, StaticExtTapSinkUdp) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be added in a dedicated integration test file for tap_sinks/udp_sink.

@adisuissa
Copy link
Copy Markdown
Contributor

Sure, I can do that. this is complicated because there is no udp server there. I am still thinking...

one more question, except Matt and wbpcode, who else can sponsor this extension? code is very easy and it is configurable. Therefore, the risk is the lowest. From the senior owner in this link, who can be contacted?

For non-contrib extensions it is better to find an owner that has some need for this extension (or a very close one). Each new extension adds some overhead to the maintainers, as they will need to address issues and direct the future development of the extension.
cc @envoyproxy/envoy-maintainers if anyone can co-own the newly proposed UDP TAP-sink extension.

The reason that I don't prefer to go contrib is that it doesn't match current design. As you know, no matter http or transport tap, both have performance issues, and sometimes, envoy building product doesn't include contrib. There is no other option if user wants to debug traffic in TLS connection(especially TLS1.3).

Many companies add their own extensions (not necessarily in the Envoy-proxy repo), and link them together.
I do see the benefit of having your extension as part of the Envoy repo, but if there's no potential owner, then having it in the contrib directory seems like a good idea to me.

At same time, let me study on how to write code in contrib.

thanks Cliff

@coolg92003
Copy link
Copy Markdown
Contributor Author

Hi @adisuissa, @ashishb-solo @wbpcode ,
Seem I am too much self-confidence 😅 and I spent lots of time to convert from "envoy extension" to "contrib extension".
Now the only left thing is where to add instruction on configure "tap custom_sink + udp sink extension", below is my two suggestions:

  1. Add in tap operation and administration
    1.1) add one example in below link for transport tap at
    tap-transport-socket-configuration
    image

    1.2) add one example in below link for http tap at
    config-http-filters-tap
    image

  2. Or, add a link of issue Add UDP sink in file api/envoy/config/tap/v3/common.proto of comment of "customer_sink" as below:
    image

I prefer to 2), any changes can be updated continuously in comment of issue, and no extra other work.

thanks
Cliff

@wbpcode wbpcode self-assigned this Jan 7, 2025
Copy link
Copy Markdown
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your great contribution. Some initial comments to start the review.

Comment thread source/extensions/common/tap/tap.h
Comment thread api/BUILD
Copy link
Copy Markdown
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution. Some new comments are added.

TapCommon::SinkPtr UdpTapSinkFactory::createTransportSinkPtr(
const Protobuf::Message& config,
Server::Configuration::TransportSocketFactoryContext& tsf_context) {
ENVOY_LOG_MISC(trace, "{}: Create UDP sink in transport context", __func__);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think __func__ is unnecessary because ENVOY_LOG macro will print the line number also?

TapCommon::SinkPtr
UdpTapSinkFactory::createHttpSinkPtr(const Protobuf::Message& config,
Server::Configuration::FactoryContext& http_context) {
ENVOY_LOG_MISC(trace, "{}: Create UDP sink in http context", __func__);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

Comment on lines +30 to +32
config, http_context.serverFactoryContext()
.messageValidationContext()
.staticValidationVisitor()));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use messageValidationVisitor from http_context directly if there is no special reason.

class UdpTapSinkFactory : public TapCommon::TapSinkFactory {
public:
~UdpTapSinkFactory() override = default;
std::string category() const override { return "envoy.tap.sinks.udp"; }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you shouldn't overwrite the category() method.

Comment on lines +23 to +30
// below one is only for UT because
// it can't control return value of writePacket if not add below function.
UdpTapSink(Network::UdpPacketWriterPtr&& utUdpPacketWriter)
: udp_packet_writer_(std::move(utUdpPacketWriter)) {
std::string utUdpServerAddress("127.0.0.1");
udp_server_address_ =
Network::Utility::parseInternetAddressNoThrow(utUdpServerAddress, 8080, false);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is only used for unit, it would be better to create a derived class in the unit test files and move this method to the test files.

Or it would be better to let the constructor to take both the address and writer.

@wbpcode
Copy link
Copy Markdown
Member

wbpcode commented Jan 16, 2025

LGTM. Thanks. Please merge main and resolve the conflict. Thanks again. :)

fchen7 added 11 commits January 16, 2025 05:21
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Signed-off-by: fchen7 <cliff.chen@nokia-sbell.com>
Copy link
Copy Markdown
Member

@wbpcode wbpcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks.

@wbpcode wbpcode merged commit 1b5740a into envoyproxy:main Jan 16, 2025
@coolg92003
Copy link
Copy Markdown
Contributor Author

hi @wbpcode , @adisuissa @ashishb-solo,
Really appreciated your great effort on this PR!
Have a nice day!
Cliff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants