Repository navigation
Milestone
Description
TLDR:
The XDP packet context is populated with the TCP header information only for n3 traffic, but not for traffic on the n6 interface. Consequently, the source and destination ports are not set, making it impossible to apply an SDF filter on the downlink side for TCP traffic.
Deployment architecture
graph LR
UE["UE (192.168.60.100)"] --> GNB["(192.168.60.50)
GNB
(192.168.80.50)"]
GNB --> eUPF["(192.168.80.200)
eUPF
(192.168.90.200)"]
eUPF --> GW["GW (192.168.90.100)"]
Issue report
Test
- The UE has an active PDU session with the IP 10.45.0.2
- From the GW, a netcat server is set to listen for TCP packets
nc -l -p 20000 -s 192.168.90.100. - From the UE, a TCP message is sent to the GW with the command
nc 192.168.90.100 20000 -s 10.45.0.2 -p 21000.
eUPF behaviour
In the method match_sdf_filter_ipv4, on the downlink side, ctx->tcp and ctx->upd are not set, resulting in both packet_src_port and packet_dst_port being equal to 0.
static __always_inline __u8 match_sdf_filter_ipv4(const struct packet_context *ctx, const struct sdf_filter *sdf) {
...
__u16 packet_src_port = 0;
__u16 packet_dst_port = 0;
if(ctx->udp) {
packet_src_port = bpf_ntohs(ctx->udp->source);
packet_dst_port = bpf_ntohs(ctx->udp->dest);
} else if (ctx->tcp) {
packet_src_port = bpf_ntohs(ctx->tcp->source);
packet_dst_port = bpf_ntohs(ctx->tcp->dest);
}
...
}Expected behaviour
The TCP header should be parsed, and the source and destination ports should be set to 20000 and 21000, respectively, to apply eventual SDF filters.
Temporary solution
To solve the issue, I've changed the following line in the n3n6_entrypoint.c file:
static __always_inline enum xdp_action handle_ip4(struct packet_context *ctx) {
int l4_protocol = parse_ip4(ctx);
switch (l4_protocol) {
case IPPROTO_ICMP: {
increment_counter(ctx->counters, rx_icmp);
break;
}
case IPPROTO_UDP:
increment_counter(ctx->counters, rx_udp);
if (GTP_UDP_PORT == parse_udp(ctx)) {
upf_printk("upf: gtp-u received");
increment_counter(ctx->n3_n6_counter, rx_n3);
return handle_gtpu(ctx);
}
break;
case IPPROTO_TCP:
increment_counter(ctx->counters, rx_tcp);
+ parse_tcp(ctx);
break;
default:
increment_counter(ctx->counters, rx_other);
return DEFAULT_XDP_ACTION;
}
increment_counter(ctx->n3_n6_counter, rx_n6);
return handle_n6_packet_ipv4(ctx);
}Let me know any additional details you may need,
Thank you in advance!
Activity
pirog-spb commentedon Apr 14, 2025
@xAlessandroC FYI fixed in #606