Skip to content

Commit 1618cbe

Browse files
authored
Merge pull request kmesh-net#83 from Eeshu-Yadav/feat/tlv-listener-filter-60_new
feat: Implement TLV listener filter support
2 parents 7405f98 + 9f932bd commit 1618cbe

File tree

17 files changed

+1055
-7
lines changed

17 files changed

+1055
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,29 @@ docker rm -f backend1 backend2 orion-proxy
109109

110110
For detailed Docker configuration options, see [docker/README.md](docker/README.md).
111111

112+
## Examples and Demos
113+
114+
### TLV Listener Filter Demo
115+
116+
Orion includes a comprehensive TLV (Type-Length-Value) listener filter demo compatible with the Kmesh project for service mesh integration. This demo provides end-to-end testing of the TLV filter functionality.
117+
118+
To test the TLV filter:
119+
120+
```bash
121+
cd examples/tlv-filter-demo
122+
./test_tlv_config.sh
123+
```
124+
125+
This demo will:
126+
- Start Orion with TLV filter configuration matching Kmesh format
127+
- Load the TLV listener filter using TypedStruct configuration
128+
- Send actual TLV packets to test the filter functionality
129+
- Extract and verify original destination information from TLV data
130+
- Show debug logs confirming successful TLV processing
131+
- Verify compatibility with Kmesh TLV configuration format
132+
133+
134+
For detailed information, see [examples/tlv-filter-demo/README.md](examples/tlv-filter-demo/README.md).
112135

113136
<!-- ## Contributing -->
114137
<!-- If you're interested in being a contributor and want to get involved in developing Orion Proxy, please see [CONTRIBUTING](CONTRIBUTING.md) for more details on submitting patches and the contribution workflow. -->

envoy-data-plane-api/build.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ use glob::glob;
55
/// std::env::set_var("PROTOC", The Path of Protoc);
66
fn main() -> std::io::Result<()> {
77
let descriptor_path = PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("proto_descriptor.bin");
8-
let protos: Vec<PathBuf> = glob("data-plane-api/envoy/**/v3/*.proto").unwrap().filter_map(Result::ok).collect();
8+
let mut protos: Vec<PathBuf> = glob("data-plane-api/envoy/**/v3/*.proto").unwrap().filter_map(Result::ok).collect();
9+
10+
let udpa_protos: Vec<PathBuf> = glob("xds/udpa/**/*.proto").unwrap().filter_map(Result::ok).collect();
11+
protos.extend(udpa_protos);
12+
13+
let custom_protos: Vec<PathBuf> = glob("../proto/**/*.proto").unwrap().filter_map(Result::ok).collect();
14+
protos.extend(custom_protos);
915

1016
let include_paths = [
1117
"data-plane-api/",
@@ -17,6 +23,7 @@ fn main() -> std::io::Result<()> {
1723
"prometheus-client-model/",
1824
"cel-spec/proto",
1925
"protobuf/src/",
26+
"../proto/",
2027
];
2128

2229
let mut config = prost_build::Config::new();

examples/tlv-filter-demo/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# TLV Filter Demo
2+
3+
This demo showcases Orion's TLV (Type-Length-Value) listener filter implementation, compatible with Kmesh configurations.
4+
5+
## Quick Test
6+
7+
Run the automated test script:
8+
9+
```bash
10+
./test_tlv_config.sh
11+
```
12+
13+
This script:
14+
1. Validates Orion configuration loading
15+
2. Tests TLV filter integration
16+
3. Optionally tests end-to-end packet processing (if client is available)
17+
18+
## Configuration
19+
20+
The TLV filter is configured in `orion-config.yaml`:
21+
22+
```yaml
23+
listeners:
24+
- name: tlv_demo_listener
25+
address: 0.0.0.0:9000
26+
filter_chains:
27+
- filters:
28+
- name: envoy.listener.kmesh_tlv
29+
typed_config:
30+
"@type": type.googleapis.com/envoy.extensions.filters.listener.kmesh_tlv.v3.KmeshTlv
31+
```
32+
33+
## Manual Testing
34+
35+
### Start Orion
36+
```bash
37+
../../target/debug/orion -c orion-config.yaml
38+
```
39+
40+
### Send TLV Packets
41+
```bash
42+
rustc send_tlv.rs -o send_tlv
43+
./send_tlv <ip> <port>
44+
```
45+
46+
The client constructs TLV packets containing original destination information and sends them to the Orion listener for testing the filter's TLV processing capabilities.
47+
48+
## TLV Client
49+
50+
The included Rust client (`send_tlv.rs`) is used for testing the TLV filter:
51+
52+
- **Purpose**: Constructs and sends TLV packets to test the filter's processing
53+
- **Functionality**: Encodes original destination IP/port in TLV format and sends to Orion listener
54+
- **Usage**: Compile with `rustc send_tlv.rs -o send_tlv` then run `./send_tlv <ip> <port>`
55+
- **Protocol**: Supports both IPv4 and IPv6 addresses in TLV packets
56+
57+
### Protocol Buffer
58+
```protobuf
59+
syntax = "proto3";
60+
package envoy.extensions.filters.listener.kmesh_tlv.v3;
61+
62+
message KmeshTlv {}
63+
```
64+
65+
### Configuration Parameters
66+
- **Filter Name**: `envoy.listener.kmesh_tlv`
67+
- **Type URL**: `type.googleapis.com/envoy.extensions.filters.listener.kmesh_tlv.v3.KmeshTlv`
68+
69+
### TLV Protocol Support
70+
- **TLV_TYPE_SERVICE_ADDRESS (0x1)**: Service address information
71+
- **TLV_TYPE_ENDING (0xfe)**: End marker
72+
- **Maximum TLV Length**: 256 bytes
73+
74+
## Architecture
75+
76+
```
77+
Client → Orion Listener → TLV Filter → Filter Chains → Backend
78+
79+
TLV Processing
80+
(Extract original destination)
81+
```
82+
83+
## Kmesh Compatibility
84+
85+
Fully compatible with Kmesh project configurations using identical protobuf package names and TypedStruct configuration pattern.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Orion Configuration with TLV Listener Filter Enabled
2+
3+
runtime:
4+
num_cpus: 1
5+
num_runtimes: 1
6+
7+
logging:
8+
log_level: "debug"
9+
10+
envoy_bootstrap:
11+
admin:
12+
address:
13+
socket_address:
14+
address: "127.0.0.1"
15+
port_value: 9901
16+
17+
static_resources:
18+
listeners:
19+
- name: "tlv_demo_listener"
20+
address:
21+
socket_address:
22+
address: "0.0.0.0"
23+
port_value: 10000
24+
listener_filters:
25+
- name: "envoy.listener.kmesh_tlv"
26+
typed_config:
27+
"@type": "type.googleapis.com/udpa.type.v1.TypedStruct"
28+
"type_url": "type.googleapis.com/envoy.extensions.filters.listener.kmesh_tlv.v3.KmeshTlv"
29+
"value": {}
30+
filter_chains:
31+
- name: "default_filter_chain"
32+
filters:
33+
- name: "envoy.filters.network.http_connection_manager"
34+
typedConfig:
35+
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
36+
codec_type: AUTO
37+
stat_prefix: tlv_demo
38+
httpFilters:
39+
- name: "envoy.filters.http.router"
40+
typedConfig:
41+
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
42+
routeConfig:
43+
name: "local_route"
44+
virtualHosts:
45+
- name: "demo"
46+
domains: ["*"]
47+
routes:
48+
- match:
49+
prefix: "/"
50+
direct_response:
51+
status: 200
52+
body:
53+
inline_string: "TLV Filter Test - Success!"
54+
55+
clusters:
56+
- name: "dummy_cluster"
57+
connect_timeout: 0.25s
58+
type: STATIC
59+
lb_policy: ROUND_ROBIN
60+
load_assignment:
61+
endpoints:
62+
- lb_endpoints:
63+
- endpoint:
64+
address:
65+
socket_address:
66+
address: "127.0.0.1"
67+
port_value: 8080
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// SPDX-FileCopyrightText: © 2025 kmesh authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
// Copyright 2025 kmesh authors
5+
//
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
//
20+
21+
use std::env;
22+
use std::io::Write;
23+
use std::net::{TcpStream, IpAddr};
24+
25+
fn construct_tlv_packet(ip: &str, port: u16) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
26+
// Parse IP address
27+
let ip_addr: IpAddr = ip.parse()?;
28+
let (ip_bytes, content_len) = match ip_addr {
29+
IpAddr::V4(ipv4) => (ipv4.octets().to_vec(), 6u32), // 4 bytes IP + 2 bytes port
30+
IpAddr::V6(ipv6) => (ipv6.octets().to_vec(), 18u32), // 16 bytes IP + 2 bytes port
31+
};
32+
33+
// Pack port as big-endian
34+
let port_bytes = port.to_be_bytes();
35+
36+
// TLV structure:
37+
// Type: 0x01 (service address)
38+
// Length: 4 bytes (big-endian)
39+
// Content: IP + Port
40+
// End: 0xfe
41+
42+
let content = [ip_bytes, port_bytes.to_vec()].concat();
43+
let length = content_len.to_be_bytes();
44+
45+
let mut tlv_packet = vec![0x01]; // Type
46+
tlv_packet.extend_from_slice(&length); // Length
47+
tlv_packet.extend_from_slice(&content); // Content
48+
49+
// End marker: Type 0xfe, Length 0
50+
tlv_packet.push(0xfe); // End type
51+
tlv_packet.extend_from_slice(&0u32.to_be_bytes()); // End length (0)
52+
53+
Ok(tlv_packet)
54+
}
55+
56+
fn send_tlv_packet(ip: &str, port: u16, listener_host: &str, listener_port: u16) -> Result<(), Box<dyn std::error::Error>> {
57+
// Create TLV packet
58+
let tlv_data = construct_tlv_packet(ip, port)?;
59+
println!("Constructed TLV packet: {:02x?}", tlv_data);
60+
61+
// Create HTTP request to follow
62+
let http_request = b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";
63+
64+
// Combine TLV + HTTP
65+
let mut packet = tlv_data;
66+
packet.extend_from_slice(http_request);
67+
68+
// Send to listener
69+
let mut stream = TcpStream::connect((listener_host, listener_port))?;
70+
stream.write_all(&packet)?;
71+
72+
println!("✅ Sent TLV packet with original destination {}:{}", ip, port);
73+
Ok(())
74+
}
75+
76+
fn main() -> Result<(), Box<dyn std::error::Error>> {
77+
let args: Vec<String> = env::args().collect();
78+
79+
if args.len() != 3 {
80+
eprintln!("Usage: {} <ip> <port>", args[0]);
81+
std::process::exit(1);
82+
}
83+
84+
let ip = &args[1];
85+
let port: u16 = args[2].parse()?;
86+
87+
match send_tlv_packet(ip, port, "127.0.0.1", 10000) {
88+
Ok(()) => {
89+
std::process::exit(0);
90+
}
91+
Err(e) => {
92+
eprintln!("❌ Failed to send TLV packet: {}", e);
93+
std::process::exit(1);
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)