clat: print translation statistics during deactivation

Print some statistics about the translation when the connection goes
down:

  clat: stats: egress (v4 to v6): tcp 1275, udp 191, icmp 9, other 0, dropped 2; ingress (v6 to v4): tcp 1669, udp 272, icmp 0, other 0, fragment 136, dropped 0

Those counters can be used to better understand what's going wrong in
case of problems; for example, if the packets are being dropped in the
ingress path or in the egress one.
This commit is contained in:
Beniamino Galvani 2026-02-06 17:32:42 +01:00
parent 112190d09a
commit a4e30ee849
3 changed files with 75 additions and 0 deletions

View file

@ -33,6 +33,7 @@
char _license[] SEC("license") = "GPL";
struct clat_config config;
struct clat_stats stats;
#ifdef DEBUG
/* Note: when enabling debugging, you also need to add CAP_PERFMON
@ -611,8 +612,25 @@ clat_handle_v4(struct __sk_buff *skb, bool has_eth)
*ip6h = dst_hdr;
switch (dst_hdr.nexthdr) {
case IPPROTO_ICMPV6:
__sync_fetch_and_add(&stats.egress_icmp, 1);
break;
case IPPROTO_TCP:
__sync_fetch_and_add(&stats.egress_tcp, 1);
break;
case IPPROTO_UDP:
__sync_fetch_and_add(&stats.egress_udp, 1);
break;
default:
__sync_fetch_and_add(&stats.egress_other, 1);
break;
}
ret = bpf_redirect(skb->ifindex, 0);
out:
if (ret == TC_ACT_SHOT)
__sync_fetch_and_add(&stats.egress_dropped, 1);
return ret;
}
@ -1125,8 +1143,27 @@ clat_handle_v6(struct __sk_buff *skb, bool has_eth)
*iph = dst_hdr;
if (fragmented)
__sync_fetch_and_add(&stats.ingress_fragment, 1);
switch (dst_hdr.protocol) {
case IPPROTO_ICMP:
__sync_fetch_and_add(&stats.ingress_icmp, 1);
break;
case IPPROTO_TCP:
__sync_fetch_and_add(&stats.ingress_tcp, 1);
break;
case IPPROTO_UDP:
__sync_fetch_and_add(&stats.ingress_udp, 1);
break;
default:
__sync_fetch_and_add(&stats.ingress_other, 1);
break;
}
ret = bpf_redirect(skb->ifindex, BPF_F_INGRESS);
out:
if (ret == TC_ACT_SHOT)
__sync_fetch_and_add(&stats.ingress_dropped, 1);
return ret;
}

View file

@ -11,4 +11,20 @@ struct clat_config {
unsigned pref64_len;
};
struct clat_stats {
/* egress: v4 to v6 */
__u64 egress_tcp;
__u64 egress_udp;
__u64 egress_icmp;
__u64 egress_other;
__u64 egress_dropped;
/* ingress: v6 to v4 */
__u64 ingress_tcp;
__u64 ingress_udp;
__u64 ingress_icmp;
__u64 ingress_other;
__u64 ingress_fragment;
__u64 ingress_dropped;
};
#endif

View file

@ -5660,6 +5660,28 @@ _l3_clat_destroy(NML3Cfg *self)
char buf[100];
int err;
if (self->priv.p->clat_bpf) {
const struct clat_stats *s = &self->priv.p->clat_bpf->bss->stats;
_LOGT("clat: stats:"
" egress (v4 to v6): tcp %" G_GUINT64_FORMAT ", udp %" G_GUINT64_FORMAT
", icmp %" G_GUINT64_FORMAT ", other %" G_GUINT64_FORMAT
", dropped %" G_GUINT64_FORMAT "; ingress (v6 to v4): tcp %" G_GUINT64_FORMAT
", udp %" G_GUINT64_FORMAT ", icmp %" G_GUINT64_FORMAT ", other %" G_GUINT64_FORMAT
", fragment %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT,
(guint64) s->egress_tcp,
(guint64) s->egress_udp,
(guint64) s->egress_icmp,
(guint64) s->egress_other,
(guint64) s->egress_dropped,
(guint64) s->ingress_tcp,
(guint64) s->ingress_udp,
(guint64) s->ingress_icmp,
(guint64) s->ingress_other,
(guint64) s->ingress_fragment,
(guint64) s->ingress_dropped);
}
if (self->priv.p->clat_ingress_link) {
err = bpf_link__destroy(self->priv.p->clat_ingress_link);
if (err != 0) {