diff --git a/src/core/bpf/clat.bpf.c b/src/core/bpf/clat.bpf.c index e44817fc3a..97d74a6191 100644 --- a/src/core/bpf/clat.bpf.c +++ b/src/core/bpf/clat.bpf.c @@ -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; } diff --git a/src/core/bpf/clat.h b/src/core/bpf/clat.h index 3d926b527f..4a8adba58d 100644 --- a/src/core/bpf/clat.h +++ b/src/core/bpf/clat.h @@ -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 diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index dfb881ebc1..9bb272df10 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -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) {