zenith-stack 0.1.0

Zenith 全协议栈框架:AF_XDP + eBPF + TLS 1.3 + HTTP/1-2-3 + Web + Proxy + WAF,按需导入
Documentation
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Zenith 统计计数逻辑 - 统计专用
 *
 * 功能:
 * - per-CPU 统计计数(无锁、无原子操作)
 * - 可由用户态读取并聚合
 * - 支持双 Bank 热更新
 */

#include "xdp_common.h"

/*
 * 统计专用 XDP 程序
 * 主要用于统计场景,不做复杂转发
 */
SEC("xdp")
int zenith_xdp_stats(struct xdp_md *ctx)
{
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;
    u32 queue_id;
    u32 fail_closed;

    /* 读取运行时配置(§3.1.5:fallback 策略由 CONFIG_MAP 承载,
     * 与 xdp_main/xdp_redirect 保持同一策略语义) */
    fail_closed = get_config_u32(CONFIG_KEY_FAIL_CLOSED);

    /* 基础长度校验 */
    if ((void *)(data + ETH_HLEN) > data_end) {
        update_stats(STATS_RX_DROP_SHORT, 1);
        return XDP_DROP;
    }

    queue_id = ctx->rx_queue_index;
    /* 统计场景:此处对通过基础长度校验的所有包计数(含将被 PASS/DROP 的包)。
     * 语义不同于 xdp_main.c:xdp_main 仅在全部 L2/L3/L4 校验通过、
     * 即将重定向到 AF_XDP 时才递增 STATS_RX_PACKETS(过滤场景的"成功导流计数")。
     * 两者服务于不同观测目的,聚合时不可混用。 */
    update_stats(STATS_RX_PACKETS, 1);

    /* 数据包分类统计 */
    struct ethhdr *eth = data;
    if (eth->h_proto == bpf_htons(ETH_P_IP)) {
        if ((void *)(data + sizeof(struct ethhdr) + sizeof(struct iphdr)) <= data_end) {
            struct iphdr *iph = (struct iphdr *)(eth + 1);

            /* 按协议分类统计 */
            switch (iph->protocol) {
            case IPPROTO_TCP:
                update_stats(STATS_RX_VALID, 1);
                break;
            case IPPROTO_UDP:
                update_stats(STATS_RX_VALID, 1);
                break;
            case IPPROTO_ICMP:
                update_stats(STATS_RX_VALID, 1);
                break;
            default:
                break;
            }
        }
    } else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
        update_stats(STATS_RX_VALID, 1);
    }

    /*
     * 尝试重定向到 AF_XDP
     * (Bank 切换由用户态 bpf_link update_prog 完成,内核态不读活动 Bank)
     */
    u32 *xsk_fd;
    xsk_fd = bpf_map_lookup_elem(&xsk_map, &queue_id);
    if (!xsk_fd) {
        /* 无对应 XSK 映射:遵循全局 fail_closed 策略(与 xdp_main 一致,
         * fail_closed=1 时 DROP,否则 PASS 回退内核协议栈) */
        update_stats(STATS_RX_DROP_NO_XSK, 1);
        if (fail_closed)
            return XDP_DROP;
        return XDP_PASS;
    }

    update_stats(STATS_REDIRECTED, 1);
    return bpf_redirect_map(&xsk_map, queue_id, XDP_PASS);
}

char _license[] SEC("license") = "GPL";