Skip to content

Conversation

@VivekSubr
Copy link
Contributor

@VivekSubr VivekSubr commented Jan 12, 2026

Commit Message:
Additional Description: Adding apis to setsockopt and getsockopt to dynamic modules abi... this is a use case un-supported by wasm filters.
Risk Level: Low, new apis
Testing:
Tested manually, verified using pcap, test code is available here: https://github.com/VivekSubr/Client-Server/tree/main/proxy/envoy/dynamic_modules/dscp_filter

Pcap output,

  • Request header
    04:29:28.602316 IP (tos 0xb8, ttl 64, id 22637, offset 0, flags [DF], proto TCP (6), length 52)
    127.0.0.1.46436 > 127.0.0.1.1447: Flags [.], cksum 0xfe28 (incorrect -> 0xe431), seq 1, ack 1, win 512, options [nop,nop,TS val 3944218569 ecr 3944218569], length 0

  • Response header
    13:35:09.281451 IP (tos 0x88, ttl 64, id 49366, offset 0, flags [DF], proto TCP (6), length 52)
    127.0.0.1.10000 > 127.0.0.1.43208: Flags [F.], cksum 0xfe28 (incorrect -> 0xcaaa), seq 202, ack 122, win 512, options [nop,nop,TS val 407378800 ecr 407378800], length 0

Docs Changes: NA? I think dynamic modules apis aren't documented function by function.

Release Notes:
Added new apis,

envoy_dynamic_module_callback_http_set_socket_option_int
envoy_dynamic_module_callback_http_set_socket_option_bytes
envoy_dynamic_module_callback_http_get_socket_option_int
envoy_dynamic_module_callback_http_get_socket_option_bytes

Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Add set_socket_option_int, set_socket_option_bytes, get_socket_option_int,
and get_socket_option_bytes method declarations to the EnvoyHttpFilter trait
to match the implementations in EnvoyHttpFilterImpl.

Also remove orphan get_socket_options method that had no trait declaration.

Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
This reverts commit f672799.

Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: Vivek Subramanian <[email protected]>
Comment on lines 2538 to 2545
/**
* envoy_dynamic_module_type_socket_direction represents whether the socket option should be
* applied to the upstream (outgoing to backend) or downstream (incoming from client) connection.
*/
typedef enum envoy_dynamic_module_type_socket_direction {
envoy_dynamic_module_type_socket_direction_Upstream = 0,
envoy_dynamic_module_type_socket_direction_Downstream = 1,
} envoy_dynamic_module_type_socket_direction;
Copy link
Member

Choose a reason for hiding this comment

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

Please move this at the end of the Common Types segment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 3422 to 3495
// ---------------------- HTTP filter socket option callbacks --------------------

/**
* envoy_dynamic_module_callback_http_set_socket_option_int sets an integer socket option with
* the given level, name, and state.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object.
* @param level is the socket option level (e.g., SOL_SOCKET).
* @param name is the socket option name (e.g., SO_KEEPALIVE).
* @param state is the socket state at which this option should be applied. For downstream
* sockets, this is ignored since the socket is already connected.
* @param direction specifies whether to apply to upstream or downstream socket.
* @param value is the integer value for the socket option.
* @return true if the operation is successful, false otherwise.
*/
bool envoy_dynamic_module_callback_http_set_socket_option_int(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, int64_t level, int64_t name,
envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction, int64_t value);

/**
* envoy_dynamic_module_callback_http_set_socket_option_bytes sets a bytes socket option with
* the given level, name, and state.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object.
* @param level is the socket option level.
* @param name is the socket option name.
* @param state is the socket state at which this option should be applied. For downstream
* sockets, this is ignored since the socket is already connected.
* @param direction specifies whether to apply to upstream or downstream socket.
* @param value is the byte buffer value for the socket option.
* @return true if the operation is successful, false otherwise.
*/
bool envoy_dynamic_module_callback_http_set_socket_option_bytes(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, int64_t level, int64_t name,
envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction,
envoy_dynamic_module_type_module_buffer value);

/**
* envoy_dynamic_module_callback_http_get_socket_option_int retrieves an integer socket option
* value.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object.
* @param level is the socket option level.
* @param name is the socket option name.
* @param state is the socket state.
* @param direction specifies whether to get from upstream or downstream socket.
* @param value_out is the pointer to store the retrieved integer value.
* @return true if the option is found, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_socket_option_int(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, int64_t level, int64_t name,
envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction, int64_t* value_out);

/**
* envoy_dynamic_module_callback_http_get_socket_option_bytes retrieves a bytes socket option
* value.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object.
* @param level is the socket option level.
* @param name is the socket option name.
* @param state is the socket state.
* @param direction specifies whether to get from upstream or downstream socket.
* @param value_out is the pointer to store the retrieved buffer. The buffer is owned by Envoy and
* valid until the filter is destroyed.
* @return true if the option is found, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_socket_option_bytes(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, int64_t level, int64_t name,
envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction,
envoy_dynamic_module_type_envoy_buffer* value_out);
Copy link
Member

Choose a reason for hiding this comment

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

Please move this to end of the HTTP Filter Callbacks segment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
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 the update, some some comments are added.

Comment on lines 1384 to 1386
if (!validateHttpSocketState(state)) {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

use ASSERT rather then if check because this state should never be invalid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines +544 to +569
void DynamicModuleHttpFilter::storeSocketOptionInt(
int64_t level, int64_t name, envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction, int64_t value) {
socket_options_.push_back(
{level, name, state, direction, /*is_int=*/true, value, /*byte_value=*/std::string()});
}

void DynamicModuleHttpFilter::storeSocketOptionBytes(
int64_t level, int64_t name, envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction, absl::string_view value) {
socket_options_.push_back(
{level, name, state, direction, /*is_int=*/false, /*int_value=*/0, std::string(value)});
}

bool DynamicModuleHttpFilter::tryGetSocketOptionInt(
int64_t level, int64_t name, envoy_dynamic_module_type_socket_option_state state,
envoy_dynamic_module_type_socket_direction direction, int64_t& value_out) const {
for (const auto& opt : socket_options_) {
if (opt.level == level && opt.name == name && opt.state == state &&
opt.direction == direction && opt.is_int) {
value_out = opt.int_value;
return true;
}
}
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

This means we can only get the options that set by this single dynamic module, if there are multiple modules or options from other filters, seems we cannot get it?

As a initial version, I have no strong point to that, but seems we should could improve it? cc @agrawroh

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the network filter does the same thing... yeah, that does make the get_socket_option of not much use, but the doing getsockopt is tricky - what socket will you do it on?

Copy link
Member

Choose a reason for hiding this comment

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

I think it does make sense to improve it if we can but it's okay if we wanna do that separately for both Network & HTTP later in a different PR.

Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Signed-off-by: VivekSubr <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants