Skip to content

Commit 9de45b9

Browse files
committed
refactor: nat v3 runtime and simplify ipv4 nat keys
1 parent a93ba5f commit 9de45b9

File tree

17 files changed

+263
-510
lines changed

17 files changed

+263
-510
lines changed

landscape-ebpf/src/bpf/land_nat4_v3.h

Lines changed: 97 additions & 102 deletions
Large diffs are not rendered by default.

landscape-ebpf/src/bpf/land_nat_common.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,14 @@ struct nat_mapping_key_v4 {
6464
// egress: Cp
6565
// ingress: Np
6666
__be16 from_port;
67-
// 0 means wildcard across WAN interfaces.
68-
u32 wan_ifindex;
6967
// egress: Ca
7068
// ingress: Na
7169
__be32 from_addr;
7270
};
7371

74-
//
7572
struct nat_timer_key_v4 {
7673
u8 l4proto;
7774
u8 _pad[3];
78-
// 0 means wildcard across WAN interfaces.
79-
u32 wan_ifindex;
8075
// As:Ps_An:Pn
8176
struct inet4_pair pair_ip;
8277
};
@@ -100,6 +95,7 @@ struct nat_timer_value_v4 {
10095
u64 egress_bytes;
10196
u64 egress_packets;
10297
u32 cpu_id;
98+
u32 ifindex;
10399
};
104100

105101
//

landscape-ebpf/src/bpf/land_nat_v3.bpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ int nat_v4_egress(struct __sk_buff *skb) {
131131
lookup.created || lookup.is_static, lookup.state, &ct_value);
132132
if (ret == TIMER_NOT_FOUND || ret == TIMER_ERROR) {
133133
if (lookup.created && !lookup.is_static) {
134-
nat4_v3_delete_mapping_and_state(pkg_offset.l4_protocol, skb->ifindex, nat_addr.addr,
134+
nat4_v3_delete_mapping_and_state(pkg_offset.l4_protocol, nat_addr.addr,
135135
lookup.egress->port, ip_pair.src_addr.addr,
136136
ip_pair.src_port);
137137
(void)nat4_v3_queue_push(pkg_offset.l4_protocol, &lookup.alloc_item);

landscape-ebpf/src/bpf/land_nat_v4.h

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ static __always_inline int nat_metric_try_report_v4(struct nat_timer_key_v4 *tim
240240
event->egress_bytes = timer_value->egress_bytes;
241241
event->egress_packets = timer_value->egress_packets;
242242
event->cpu_id = timer_value->cpu_id;
243-
event->ifindex = timer_key->wan_ifindex;
243+
event->ifindex = timer_value->ifindex;
244244
event->status = status;
245245
event->gress = timer_value->gress;
246246
bpf_ringbuf_submit(event, 0);
@@ -389,15 +389,13 @@ release:;
389389
egress_mapping_key.gress = NAT_MAPPING_EGRESS;
390390
egress_mapping_key.from_addr = value->client_addr.addr;
391391
egress_mapping_key.from_port = value->client_port;
392-
egress_mapping_key.wan_ifindex = key->wan_ifindex;
393392

394393
// ingress key: {INGRESS, proto, Pn, An} — from key
395394
struct nat_mapping_key_v4 ingress_mapping_key = {0};
396395
ingress_mapping_key.l4proto = key->l4proto;
397396
ingress_mapping_key.gress = NAT_MAPPING_INGRESS;
398397
ingress_mapping_key.from_addr = key->pair_ip.dst_addr.addr;
399398
ingress_mapping_key.from_port = key->pair_ip.dst_port;
400-
ingress_mapping_key.wan_ifindex = key->wan_ifindex;
401399

402400
// Check if static: lookup egress mapping, if is_static don't delete mapping entries
403401
struct nat_mapping_value_v4 *egress_val =
@@ -457,7 +455,6 @@ static __always_inline int lookup_or_new_ct(struct __sk_buff *skb, u8 l4proto, b
457455
u8 flow_id = get_flow_id(skb->mark);
458456

459457
timer_key.l4proto = l4proto;
460-
timer_key.wan_ifindex = skb->ifindex;
461458
// CT key = {As:Ps, An:Pn}
462459
__builtin_memcpy(&timer_key.pair_ip, server_nat_pair, sizeof(timer_key.pair_ip));
463460

@@ -479,6 +476,7 @@ static __always_inline int lookup_or_new_ct(struct __sk_buff *skb, u8 l4proto, b
479476
timer_value_new.create_time = bpf_ktime_get_ns();
480477
timer_value_new.flow_id = flow_id;
481478
timer_value_new.cpu_id = bpf_get_smp_processor_id();
479+
timer_value_new.ifindex = skb->ifindex;
482480
timer_value = insert_new_nat_timer(l4proto, &timer_key, &timer_value_new);
483481
if (timer_value == NULL) {
484482
return TIMER_ERROR;
@@ -497,7 +495,6 @@ insert_mappings_v4(const struct nat_mapping_key_v4 *key, const struct nat_mappin
497495
struct nat_mapping_key_v4 key_rev = {
498496
.gress = key->gress ^ GRESS_MASK,
499497
.l4proto = key->l4proto,
500-
.wan_ifindex = key->wan_ifindex,
501498
.from_addr = val->addr,
502499
.from_port = val->port,
503500
};
@@ -550,14 +547,9 @@ static int search_port_callback_v4(u32 index, struct search_port_ctx_v4 *ctx) {
550547
.gress = NAT_MAPPING_INGRESS,
551548
.l4proto = ctx->ingress_key.l4proto,
552549
.from_port = ctx->ingress_key.from_port,
553-
.wan_ifindex = ctx->ingress_key.wan_ifindex,
554550
.from_addr = 0,
555551
};
556552
struct nat_mapping_value_v4 *static_val = bpf_map_lookup_elem(&nat4_mappings, &static_key);
557-
if (!static_val) {
558-
static_key.wan_ifindex = 0;
559-
static_val = bpf_map_lookup_elem(&nat4_mappings, &static_key);
560-
}
561553
if (!static_val) {
562554
ctx->found = true;
563555
return BPF_LOOP_RET_BREAK;
@@ -592,7 +584,6 @@ ingress_lookup_or_new_mapping4(struct __sk_buff *skb, u8 ip_protocol,
592584
.gress = NAT_MAPPING_INGRESS,
593585
.l4proto = ip_protocol,
594586
.from_port = pkt_ip_pair->dst_port,
595-
.wan_ifindex = skb->ifindex,
596587
.from_addr = pkt_ip_pair->dst_addr.addr,
597588
};
598589

@@ -603,10 +594,6 @@ ingress_lookup_or_new_mapping4(struct __sk_buff *skb, u8 ip_protocol,
603594
// Fallback: try addr=0 for static mapping {INGRESS, proto, Pn, 0}
604595
ingress_key.from_addr = 0;
605596
nat_ingress_value = bpf_map_lookup_elem(&nat4_mappings, &ingress_key);
606-
if (!nat_ingress_value) {
607-
ingress_key.wan_ifindex = 0;
608-
nat_ingress_value = bpf_map_lookup_elem(&nat4_mappings, &ingress_key);
609-
}
610597
if (!nat_ingress_value) {
611598
return TC_ACT_SHOT;
612599
}
@@ -629,31 +616,19 @@ egress_lookup_or_new_mapping_v4(struct __sk_buff *skb, u8 ip_protocol, bool allo
629616
u64 curent_time = bpf_ktime_get_ns();
630617
struct nat_mapping_key_v4 egress_key = {
631618
.gress = NAT_MAPPING_EGRESS,
632-
.l4proto = ip_protocol, // 原有的 l4 层协议值
633-
.from_port = pkt_ip_pair->src_port, // 数据包中的 内网端口
634-
.wan_ifindex = skb->ifindex,
619+
.l4proto = ip_protocol, // 原有的 l4 层协议值
620+
.from_port = pkt_ip_pair->src_port, // 数据包中的 内网端口
635621
.from_addr = pkt_ip_pair->src_addr.addr, // 内网原始地址
636622
};
637623

638624
// 倒置的值
639625
struct nat_mapping_value_v4 *nat_ingress_value = NULL;
640626
struct nat_mapping_value_v4 *nat_egress_value =
641627
bpf_map_lookup_elem(&nat4_mappings, &egress_key);
642-
if (!nat_egress_value) {
643-
// Support wildcard-WAN static host mappings; dynamic entries never use ifindex=0.
644-
egress_key.wan_ifindex = 0;
645-
nat_egress_value = bpf_map_lookup_elem(&nat4_mappings, &egress_key);
646-
egress_key.wan_ifindex = skb->ifindex;
647-
}
648628
if (!nat_egress_value) {
649629
// Fallback: try addr=0 for static mapping targeting local router
650630
egress_key.from_addr = 0;
651631
nat_egress_value = bpf_map_lookup_elem(&nat4_mappings, &egress_key);
652-
if (!nat_egress_value) {
653-
egress_key.wan_ifindex = 0;
654-
nat_egress_value = bpf_map_lookup_elem(&nat4_mappings, &egress_key);
655-
}
656-
egress_key.wan_ifindex = skb->ifindex;
657632
egress_key.from_addr = pkt_ip_pair->src_addr.addr;
658633
}
659634
if (!nat_egress_value) {
@@ -688,7 +663,6 @@ egress_lookup_or_new_mapping_v4(struct __sk_buff *skb, u8 ip_protocol, bool allo
688663
{
689664
.gress = NAT_MAPPING_INGRESS,
690665
.l4proto = ip_protocol,
691-
.wan_ifindex = skb->ifindex,
692666
.from_addr = new_nat_egress_value.addr,
693667
.from_port = new_nat_egress_value.port,
694668
},
@@ -750,8 +724,7 @@ egress_lookup_or_new_mapping_v4(struct __sk_buff *skb, u8 ip_protocol, bool allo
750724
// 已经存在就查询另外一个值 并进行刷新时间
751725
struct nat_mapping_key_v4 ingress_key = {
752726
.gress = NAT_MAPPING_INGRESS,
753-
.l4proto = ip_protocol, // 原有的 l4 层协议值
754-
.wan_ifindex = egress_key.wan_ifindex,
727+
.l4proto = ip_protocol, // 原有的 l4 层协议值
755728
.from_port = nat_egress_value->port, // 数据包中的 内网端口
756729
.from_addr = nat_egress_value->addr, // 内网原始地址
757730
};

landscape-ebpf/src/bpf/nat/nat_maps.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ struct {
5757
__uint(pinning, LIBBPF_PIN_BY_NAME);
5858
} nat6_static_mappings SEC(".maps");
5959

60+
struct {
61+
__uint(type, BPF_MAP_TYPE_HASH);
62+
__type(key, struct nat_mapping_key_v4);
63+
__type(value, struct nat_mapping_value_v4);
64+
__uint(max_entries, NAT_MAPPING_CACHE_SIZE);
65+
__uint(pinning, LIBBPF_PIN_BY_NAME);
66+
} nat4_st_map SEC(".maps");
67+
6068
struct {
6169
__uint(type, BPF_MAP_TYPE_HASH);
6270
__type(key, struct nat_mapping_key_v4);

landscape-ebpf/src/bpf/nat/nat_v3_maps.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,24 @@ struct nat_timer_value_v4_v3 {
3838
u64 egress_bytes;
3939
u64 egress_packets;
4040
u32 cpu_id;
41+
u32 ifindex;
4142
u16 generation_snapshot;
4243
u8 is_final_releaser;
4344
u8 _pad0;
4445
};
4546

47+
struct {
48+
__uint(type, BPF_MAP_TYPE_HASH);
49+
__type(key, struct nat_mapping_key_v4);
50+
__type(value, struct nat_mapping_value_v4);
51+
__uint(max_entries, NAT_MAPPING_CACHE_SIZE);
52+
} nat4_dyn_map SEC(".maps");
53+
4654
struct {
4755
__uint(type, BPF_MAP_TYPE_HASH);
4856
__type(key, struct nat_mapping_key_v4);
4957
__type(value, struct nat4_mapping_state_v3);
5058
__uint(max_entries, NAT4_V3_DYNAMIC_STATE_SIZE);
51-
__uint(pinning, LIBBPF_PIN_BY_NAME);
5259
} nat4_dynamic_state_v3 SEC(".maps");
5360

5461
struct {
@@ -57,28 +64,24 @@ struct {
5764
__type(value, struct nat_timer_value_v4_v3);
5865
__uint(max_entries, NAT4_V3_TIMER_SIZE);
5966
__uint(map_flags, BPF_F_NO_PREALLOC);
60-
__uint(pinning, LIBBPF_PIN_BY_NAME);
6167
} nat4_mapping_timer_v3 SEC(".maps");
6268

6369
struct {
6470
__uint(type, BPF_MAP_TYPE_QUEUE);
6571
__type(value, struct nat4_port_queue_value_v3);
6672
__uint(max_entries, NAT4_V3_PORT_QUEUE_SIZE);
67-
__uint(pinning, LIBBPF_PIN_BY_NAME);
6873
} nat4_tcp_free_ports_v3 SEC(".maps");
6974

7075
struct {
7176
__uint(type, BPF_MAP_TYPE_QUEUE);
7277
__type(value, struct nat4_port_queue_value_v3);
7378
__uint(max_entries, NAT4_V3_PORT_QUEUE_SIZE);
74-
__uint(pinning, LIBBPF_PIN_BY_NAME);
7579
} nat4_udp_free_ports_v3 SEC(".maps");
7680

7781
struct {
7882
__uint(type, BPF_MAP_TYPE_QUEUE);
7983
__type(value, struct nat4_port_queue_value_v3);
8084
__uint(max_entries, NAT4_V3_PORT_QUEUE_SIZE);
81-
__uint(pinning, LIBBPF_PIN_BY_NAME);
8285
} nat4_icmp_free_ports_v3 SEC(".maps");
8386

8487
#endif /* __LD_NAT_V3_MAPS_H__ */

landscape-ebpf/src/bpf/share_map.bpf.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#include "landscape.h"
44
#include "nat/nat_maps.h"
5-
#include "nat/nat_v3_maps.h"
65
#include "land_wan_ip.h"
76
#include "firewall_share.h"
87
#include "metric.h"

landscape-ebpf/src/bpf/test_nat_v3_timer.bpf.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,18 @@ int nat_v4_timer_step_test(struct __sk_buff *skb) {
7979
struct nat_mapping_key_v4 ingress_key = {
8080
.gress = NAT_MAPPING_INGRESS,
8181
.l4proto = input->key.l4proto,
82-
.wan_ifindex = input->key.wan_ifindex,
8382
.from_addr = nat_addr,
8483
.from_port = nat_port,
8584
};
8685
struct nat_mapping_key_v4 egress_key = {
8786
.gress = NAT_MAPPING_EGRESS,
8887
.l4proto = input->key.l4proto,
89-
.wan_ifindex = input->key.wan_ifindex,
9088
.from_addr = client_addr,
9189
.from_port = client_port,
9290
};
9391

94-
result->ingress_mapping_exists = bpf_map_lookup_elem(&nat4_mappings, &ingress_key) ? 1 : 0;
95-
result->egress_mapping_exists = bpf_map_lookup_elem(&nat4_mappings, &egress_key) ? 1 : 0;
92+
result->ingress_mapping_exists = bpf_map_lookup_elem(&nat4_dyn_map, &ingress_key) ? 1 : 0;
93+
result->egress_mapping_exists = bpf_map_lookup_elem(&nat4_dyn_map, &egress_key) ? 1 : 0;
9694

9795
struct nat4_mapping_state_v3 *state = bpf_map_lookup_elem(&nat4_dynamic_state_v3, &ingress_key);
9896
result->state_exists = state ? 1 : 0;

landscape-ebpf/src/lib.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,10 @@ static MAP_PATHS: Lazy<LandscapeMapPath> = Lazy::new(|| {
3333
let paths = LandscapeMapPath {
3434
wan_ip: PathBuf::from(format!("{}/wan_ip_binding", ebpf_map_path)),
3535
nat6_static_mappings: PathBuf::from(format!("{}/nat_static_mapping", ebpf_map_path)),
36+
nat4_st_map: PathBuf::from(format!("{}/nat4_st_map", ebpf_map_path)),
3637

3738
nat4_mappings: PathBuf::from(format!("{}/nat4_mappings", ebpf_map_path)),
3839
nat4_mapping_timer: PathBuf::from(format!("{}/nat4_mapping_timer", ebpf_map_path)),
39-
nat4_dynamic_state_v3: PathBuf::from(format!("{}/nat4_dynamic_state_v3", ebpf_map_path)),
40-
nat4_mapping_timer_v3: PathBuf::from(format!("{}/nat4_mapping_timer_v3", ebpf_map_path)),
41-
nat4_tcp_free_ports_v3: PathBuf::from(format!("{}/nat4_tcp_free_ports_v3", ebpf_map_path)),
42-
nat4_udp_free_ports_v3: PathBuf::from(format!("{}/nat4_udp_free_ports_v3", ebpf_map_path)),
43-
nat4_icmp_free_ports_v3: PathBuf::from(format!(
44-
"{}/nat4_icmp_free_ports_v3",
45-
ebpf_map_path
46-
)),
4740

4841
firewall_ipv4_block: PathBuf::from(format!("{}/firewall_block_ip4_map", ebpf_map_path)),
4942
firewall_ipv6_block: PathBuf::from(format!("{}/firewall_block_ip6_map", ebpf_map_path)),
@@ -94,13 +87,9 @@ pub(crate) struct LandscapeMapPath {
9487
pub wan_ip: PathBuf,
9588
// NAT
9689
pub nat6_static_mappings: PathBuf,
90+
pub nat4_st_map: PathBuf,
9791
pub nat4_mappings: PathBuf,
9892
pub nat4_mapping_timer: PathBuf,
99-
pub nat4_dynamic_state_v3: PathBuf,
100-
pub nat4_mapping_timer_v3: PathBuf,
101-
pub nat4_tcp_free_ports_v3: PathBuf,
102-
pub nat4_udp_free_ports_v3: PathBuf,
103-
pub nat4_icmp_free_ports_v3: PathBuf,
10493

10594
// 防火墙黑名单
10695
pub firewall_ipv4_block: PathBuf,

landscape-ebpf/src/map_setting/mod.rs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -132,26 +132,6 @@ pub mod route;
132132

133133
pub mod event;
134134

135-
fn cleanup_obsolete_nat_v3_runtime_pins(paths: &LandscapeMapPath) {
136-
let obsolete_paths = [
137-
&paths.nat4_dynamic_state_v3,
138-
&paths.nat4_mapping_timer_v3,
139-
&paths.nat4_tcp_free_ports_v3,
140-
&paths.nat4_udp_free_ports_v3,
141-
&paths.nat4_icmp_free_ports_v3,
142-
];
143-
for path in obsolete_paths {
144-
match std::fs::remove_file(path) {
145-
Ok(()) => tracing::info!("Removed obsolete NAT v3 runtime pin: {}", path.display()),
146-
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
147-
Err(e) => tracing::warn!(
148-
"Failed to remove obsolete NAT v3 runtime pin {}: {e}",
149-
path.display()
150-
),
151-
}
152-
}
153-
}
154-
155135
pub(crate) fn init_path(paths: &LandscapeMapPath) {
156136
let landscape_builder = ShareMapSkelBuilder::default();
157137
// landscape_builder.obj_builder.debug(true);
@@ -164,12 +144,12 @@ pub(crate) fn init_path(paths: &LandscapeMapPath) {
164144
&mut landscape_open.maps.nat6_static_mappings,
165145
&paths.nat6_static_mappings,
166146
);
147+
reuse_pinned_map_or_recreate(&mut landscape_open.maps.nat4_st_map, &paths.nat4_st_map);
167148
reuse_pinned_map_or_recreate(
168149
&mut landscape_open.maps.nat4_mapping_timer,
169150
&paths.nat4_mapping_timer,
170151
);
171152
reuse_pinned_map_or_recreate(&mut landscape_open.maps.nat4_mappings, &paths.nat4_mappings);
172-
cleanup_obsolete_nat_v3_runtime_pins(paths);
173153

174154
// firewall
175155
reuse_pinned_map_or_recreate(
@@ -228,11 +208,6 @@ pub fn cleanup_pinned_maps() {
228208
// nat4_mapping_timer contains bpf_timer entries whose callbacks hold
229209
// refcounts on nat_v4 programs, preventing kernel cleanup.
230210
&MAP_PATHS.nat4_mapping_timer,
231-
&MAP_PATHS.nat4_dynamic_state_v3,
232-
&MAP_PATHS.nat4_mapping_timer_v3,
233-
&MAP_PATHS.nat4_tcp_free_ports_v3,
234-
&MAP_PATHS.nat4_udp_free_ports_v3,
235-
&MAP_PATHS.nat4_icmp_free_ports_v3,
236211
];
237212
for path in maps_to_unpin {
238213
match std::fs::remove_file(path) {

0 commit comments

Comments
 (0)