Skip to content

TCP header is not parsed on the downlink side #602

Closed

Description

@xAlessandroC

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)"]

Loading

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

  1. added this to the v0.7.1 milestone on Mar 31, 2025
  2. added theissue type on Apr 9, 2025
  3. linked a pull request that will close this issuefix: Parse TCP header #606on Apr 13, 2025
  4. pirog-spb commented on Apr 14, 2025

    @pirog-spb
    Collaborator

    @xAlessandroC FYI fixed in #606

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions