Skip to content

Commit e8897d7

Browse files
bpf: dsr: only require DSR-info on SYN packet
The DSR ingress path on a remote node currently expects DSR-info on both the SYN *and* the SYN-ACK. And clears the connection's DSR status if either of those packets doesn't carry DSR info. But it should actually be fine for the LB node to only send the DSR info on the SYN packet. So let's relax this check accordingly, and not require DSR info on the SYN-ACK. Signed-off-by: Julian Wiedmann <jwi@isovalent.com>
1 parent fe0a97c commit e8897d7

3 files changed

Lines changed: 53 additions & 2 deletions

File tree

bpf/lib/l4.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ static __always_inline __u8 tcp_flags_to_u8(__be32 value)
2929
return ((union tcp_flags)value).lower_bits;
3030
}
3131

32+
static __always_inline bool tcp_is_syn(union tcp_flags flags)
33+
{
34+
/* Match SYN, but not SYN-ACK. */
35+
return (flags.value & (TCP_FLAG_SYN | TCP_FLAG_ACK)) == TCP_FLAG_SYN;
36+
}
37+
3238
static __always_inline int
3339
l4_store_port(struct __ctx_buff *ctx, int l4_off, int port_off, __be16 port)
3440
{

bpf/lib/nodeport.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ nodeport_extract_dsr_v6(struct __ctx_buff *ctx,
583583
tmp.flags = TUPLE_F_OUT;
584584
__ipv6_ct_tuple_reverse(&tmp);
585585

586-
if (tcp_flags.value & TCP_FLAG_SYN) {
586+
if (tcp_is_syn(tcp_flags)) {
587587
/* SYN for a new connection that's not / no longer DSR.
588588
* If it's reopened, avoid sending subsequent traffic down the DSR path.
589589
*/
@@ -1962,7 +1962,7 @@ nodeport_extract_dsr_v4(struct __ctx_buff *ctx,
19621962
tmp.flags = TUPLE_F_OUT;
19631963
__ipv4_ct_tuple_reverse(&tmp);
19641964

1965-
if (tcp_flags.value & TCP_FLAG_SYN) {
1965+
if (tcp_is_syn(tcp_flags)) {
19661966
/* SYN for a new connection that's not / no longer DSR.
19671967
* If it's reopened, avoid sending subsequent traffic down the DSR path.
19681968
*/

bpf/tests/kpr_dsr_remote_node.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,27 @@ int kpr_v4_dsr_remote_node_3synack_check(__maybe_unused const struct __ctx_buff
262262
kpr_v4_dsr_remote_node_synack,
263263
sizeof(kpr_v4_dsr_remote_node_synack));
264264

265+
struct ipv4_ct_tuple tuple;
266+
struct ct_entry *ct_entry;
267+
268+
tuple.flags = TUPLE_F_IN;
269+
tuple.nexthdr = IPPROTO_TCP;
270+
tuple.daddr = v4_pod_one;
271+
tuple.saddr = v4_ext_one;
272+
tuple.sport = tcp_dst_one;
273+
tuple.dport = tcp_src_one;
274+
ipv4_ct_tuple_reverse(&tuple);
275+
276+
ct_entry = map_lookup_elem(get_ct_map4(&tuple), &tuple);
277+
if (!ct_entry)
278+
test_fatal("no CT entry for DSR found");
279+
if (!ct_entry->dsr_internal)
280+
test_fatal("CT entry doesn't have the .dsr_internal flag set");
281+
if (ct_entry->nat_addr.p4 != v4_svc_one)
282+
test_fatal("CT entry doesn't have the RevDNAT addr set");
283+
if (ct_entry->nat_port != tcp_svc_one)
284+
test_fatal("CT entry doesn't have the RevDNAT port set");
285+
265286
test_finish();
266287
}
267288

@@ -619,6 +640,30 @@ int kpr_v6_dsr_remote_node_3synack_check(__maybe_unused const struct __ctx_buff
619640
kpr_v6_dsr_remote_node_synack,
620641
sizeof(kpr_v6_dsr_remote_node_synack));
621642

643+
struct ipv6_ct_tuple tuple __align_stack_8;
644+
struct ct_entry *ct_entry;
645+
union v6addr frontend_ip = { v6_svc_one_addr };
646+
union v6addr backend_ip = { v6_pod_one_addr };
647+
union v6addr client_ip = { v6_ext_node_one_addr };
648+
649+
tuple.flags = TUPLE_F_IN;
650+
tuple.nexthdr = IPPROTO_TCP;
651+
ipv6_addr_copy(&tuple.daddr, &backend_ip);
652+
ipv6_addr_copy(&tuple.saddr, &client_ip);
653+
tuple.sport = tcp_dst_one;
654+
tuple.dport = tcp_src_one;
655+
ipv6_ct_tuple_reverse(&tuple);
656+
657+
ct_entry = map_lookup_elem(get_ct_map6(&tuple), &tuple);
658+
if (!ct_entry)
659+
test_fatal("no CT entry for DSR found");
660+
if (!ct_entry->dsr_internal)
661+
test_fatal("CT entry doesn't have the .dsr_internal flag set");
662+
if (!ipv6_addr_equals(&ct_entry->nat_addr, &frontend_ip))
663+
test_fatal("CT entry doesn't have the RevDNAT addr set");
664+
if (ct_entry->nat_port != tcp_svc_one)
665+
test_fatal("CT entry doesn't have the RevDNAT port set");
666+
622667
test_finish();
623668
}
624669

0 commit comments

Comments
 (0)