Skip to content

Commit f6d046b

Browse files
authored
Merge pull request #73 from ogournet/pfcp-be
pfcp: fix teid endianess
2 parents dd18f96 + c05d78f commit f6d046b

File tree

5 files changed

+58
-19
lines changed

5 files changed

+58
-19
lines changed

src/bpf/lib/cgn-def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "tools.h"
66
#include "if_rule-def.h"
77

8-
//#define CGN_DEBUG
8+
/* #define CGN_DEBUG */
99

1010
#ifdef CGN_DEBUG
1111
# define CGN_DBG(Fmt, ...) bpf_printk(Fmt, ## __VA_ARGS__)

src/bpf/lib/tools.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ csum_diff32(__u32 csum, __u32 from, __u32 to)
126126
static __always_inline __u32
127127
csum_diff16(__u32 csum, __u16 from, __u16 to)
128128
{
129-
return csum + (~from & 0xffff) + to;
129+
return csum_add(csum, (~from & 0xffff) + to);
130130
}
131131

132132
static __always_inline __u16

src/bpf/lib/upf.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ _handle_gtpu(struct xdp_md *ctx, struct if_rule_data *d,
178178
struct ipv6hdr *ip6h_inner;
179179
struct gtphdr *gtph;
180180
int adjust_sz, pkt_len;
181+
__u32 sum;
181182

182183
gtph = (struct gtphdr *)(udph + 1);
183184
if (gtph + 1 > data_end)
@@ -208,23 +209,34 @@ _handle_gtpu(struct xdp_md *ctx, struct if_rule_data *d,
208209

209210
if ((u->flags & UPF_FWD_FL_ACT_KEEP_OUTER_HEADER) ==
210211
UPF_FWD_FL_ACT_KEEP_OUTER_HEADER) {
211-
/* forward gtpu as-this */
212+
/* forward gtp-u as-this */
213+
sum = csum_diff32(0, iph->saddr, u->gtpu_local_addr);
214+
sum = csum_diff32(sum, iph->daddr, u->gtpu_remote_addr);
212215
iph->saddr = u->gtpu_local_addr;
213216
iph->daddr = u->gtpu_remote_addr;
217+
--iph->ttl;
218+
iph->check = csum_replace(iph->check, sum - 1);
219+
220+
if (udph->check) {
221+
sum = csum_diff16(sum, udph->source, u->gtpu_local_port);
222+
sum = csum_diff16(sum, udph->dest, u->gtpu_remote_port);
223+
sum = csum_diff32(sum, gtph->teid, u->gtpu_remote_teid);
224+
__u16 nsum = csum_replace(udph->check, sum);
225+
udph->check = nsum ?: 0xffff;
226+
}
214227
udph->source = u->gtpu_local_port;
215228
udph->dest = u->gtpu_remote_port;
216-
udph->check = 0;
217229
gtph->teid = u->gtpu_remote_teid;
218230
UPF_DBG("rewrite_gtpu: src:%pI4:%d dst:%pI4:%d teid:%x",
219231
&iph->saddr, bpf_ntohs(udph->source),
220232
&iph->daddr, bpf_ntohs(udph->dest),
221233
bpf_ntohl(gtph->teid));
222-
d->dst_addr.ip4 = iph->daddr;
223234

224235
/* metrics */
225236
++u->fwd_packets;
226237
u->fwd_bytes += pkt_len;
227238

239+
d->dst_addr.ip4 = iph->daddr;
228240
return XDP_IFR_FORWARD;
229241
}
230242

src/pfcp/pfcp_bpf.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,34 @@ extern struct data *daemon_data;
3939

4040

4141
static void
42-
_log_egress_rule(int action, struct pfcp_teid *t, int err)
42+
_log_egress_rule(int action, struct upf_fwd_rule *u, struct pfcp_teid *t, int err)
4343
{
4444
char gtpu_str[INET6_ADDRSTRLEN];
4545
char errmsg[GTP_XDP_STRERR_BUFSIZE];
46+
char action_str[60];
4647

4748
if (err)
4849
libbpf_strerror(err, errmsg, GTP_XDP_STRERR_BUFSIZE);
4950

51+
if (action == RULE_ADD &&
52+
(u->flags & UPF_FWD_FL_ACT_KEEP_OUTER_HEADER) ==
53+
UPF_FWD_FL_ACT_KEEP_OUTER_HEADER) {
54+
snprintf(action_str, sizeof (action_str),
55+
"fwd to teid:0x%.8x remote:'%s'",
56+
u->gtpu_remote_teid,
57+
inet_ntop(AF_INET, &u->gtpu_remote_addr,
58+
gtpu_str, INET6_ADDRSTRLEN));
59+
} else {
60+
strcpy(action_str, "decap");
61+
}
62+
5063
log_message(LOG_INFO, "pfcp_bpf: %s%s XDP 'egress' rule "
51-
"{local_teid:0x%.8x, local_gtpu:'%s'} %s",
64+
"{local_teid:0x%.8x, local_gtpu:'%s', %s} %s",
5265
(err) ? "Error " : "",
5366
(action == RULE_ADD) ? "adding" : "deleting",
5467
t->id,
5568
inet_ntop(AF_INET, &t->ipv4, gtpu_str, INET6_ADDRSTRLEN),
69+
action_str,
5670
(err) ? errmsg : "");
5771
}
5872

@@ -69,12 +83,14 @@ _update_egress_rule(struct pfcp_router *r, struct upf_fwd_rule *u, struct pfcp_t
6983
};
7084
int err, i;
7185

72-
for (i = 0; i < nr_cpus; i++)
86+
for (i = 0; i < nr_cpus; i++) {
7387
rule[i] = *u;
88+
rule[i].gtpu_remote_teid = htonl(u->gtpu_remote_teid);
89+
}
7490

7591
err = bpf_map__update_elem(r->bpf_data->user_egress, &key, sizeof(key),
7692
rule, sizeof(rule), flags);
77-
_log_egress_rule(RULE_ADD, t, err);
93+
_log_egress_rule(RULE_ADD, u, t, err);
7894

7995
return err ? -1 : 0;
8096
}
@@ -89,7 +105,7 @@ _delete_egress_rule(struct pfcp_router *r, struct pfcp_teid *t)
89105
};
90106
int err = bpf_map__delete_elem(r->bpf_data->user_egress, &key,
91107
sizeof(key), 0);
92-
_log_egress_rule(RULE_DEL, t, err);
108+
_log_egress_rule(RULE_DEL, NULL, t, err);
93109

94110
return err ? -1 : 0;
95111
}
@@ -138,8 +154,10 @@ _update_ingress_rule(struct pfcp_router *r, struct upf_fwd_rule *u, struct ue_ip
138154
struct upf_ingress_key key = {};
139155
int i, err = 0, err_cnt = 0;
140156

141-
for (i = 0; i < nr_cpus; i++)
157+
for (i = 0; i < nr_cpus; i++) {
142158
rule[i] = *u;
159+
rule[i].gtpu_remote_teid = htonl(u->gtpu_remote_teid);
160+
}
143161

144162
if (ue->flags & UE_IPV4) {
145163
key.flags = UE_IPV4;
@@ -399,7 +417,8 @@ pfcp_bpf_vty(struct gtp_bpf_prog *p, void *ud, struct vty *vty,
399417
if ((rule[0].flags & UPF_FWD_FL_ACT_KEEP_OUTER_HEADER) ==
400418
UPF_FWD_FL_ACT_KEEP_OUTER_HEADER) {
401419
snprintf(action_str, sizeof (action_str),
402-
"Fwd to teid 0x%08x", rule[0].gtpu_remote_teid);
420+
"Fwd to teid 0x%08x",
421+
ntohl(rule[0].gtpu_remote_teid));
403422
} else {
404423
strcpy(action_str, "Decap");
405424
}

test/upf.sh

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ setup_combined() {
3030

3131
# gtp-u
3232
ip -n cloud addr add 192.168.61.2/25 dev veth0
33-
ip -n cloud addr add 192.168.61.3/25 dev veth0
33+
ip -n cloud addr add 192.168.61.3 dev veth0
3434
ip -n cloud addr add fc::2/64 dev veth0
3535
ip addr add 192.168.61.1/25 dev upf
3636
ip addr add fc::1/64 dev upf
@@ -83,7 +83,7 @@ setup_split() {
8383

8484
# gtp-u, on access
8585
ip -n access addr add 192.168.61.2/25 dev veth0
86-
ip -n access addr add 192.168.61.3/25 dev veth0
86+
ip -n access addr add 192.168.61.3 dev veth0
8787
ip addr add 192.168.61.1/25 dev ran
8888
ip neigh add 192.168.61.2 lladdr d2:ad:ca:fe:aa:01 dev ran
8989
ip neigh add 192.168.61.3 lladdr d2:ad:ca:fe:aa:01 dev ran
@@ -167,8 +167,8 @@ pfcp-router pfcp-1
167167
debug teid add egress 17 192.168.61.1
168168
debug teid add egress 18 192.168.61.1
169169
debug teid add egress 19 192.168.61.1
170-
debug teid add fwd 4 192.168.61.1 192.168.61.2 20
171-
debug teid add fwd 20 192.168.61.1 192.168.61.3 4
170+
debug teid add fwd 2220 192.168.61.1 192.168.61.2 4
171+
debug teid add fwd 20 192.168.61.1 192.168.61.3 5
172172
" || fail "cannot execute vty commands"
173173

174174
gtpg_show "
@@ -203,11 +203,19 @@ ip netns exec $ingress_ns python3 - <<EOF
203203
import socket
204204
import struct
205205
fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
206-
fd.bind(('0.0.0.0', 2152))
206+
fd.bind(('', 2152))
207207
for i in range(0,4):
208208
data, remote = fd.recvfrom(4096)
209209
data = bytearray(data)
210-
print('CORE: RECV REPLY ! teid is 0x%08x' % struct.unpack('!I', data[4:8]))
210+
teid = struct.unpack('!I', data[4:8])[0]
211+
if teid == 5:
212+
rteid = 2220
213+
print('CORE: FWD teid %d back to %d' % (teid, rteid))
214+
data[4:8] = struct.pack('!I', rteid)
215+
data = bytes(data)
216+
fd.sendto(data, remote)
217+
else:
218+
print('CORE: RECV REPLY ! teid is 0x%08x' % struct.unpack('!I', data[4:8]))
211219
fd.close()
212220
EOF
213221
) &
@@ -237,7 +245,7 @@ Ether(src='d2:ad:ca:fe:aa:01', dst='d2:f0:0c:ba:bb:01') /
237245
UDP(sport=2152, dport=2152) /
238246
GTP_U_Header(teid=20, gtp_type=255) /
239247
IP(src='10.0.0.3',dst='8.8.8.8') /
240-
ICMP(type='echo-request',id=126),
248+
ICMP(type='echo-request',id=113),
241249
]
242250
"
243251
fi

0 commit comments

Comments
 (0)