You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为IP/CIDR创建LPM trie记录切片以使用ebpf批量API

用cilium/ebpf的BatchUpdate/BatchDelete优化XDP防火墙IP黑名单批量操作

第一步:定义LPM Trie键结构体

eBPF的LPM trie map要求键必须包含前缀长度和IP地址两个字段,先在Go代码里定义对应的结构体(要和你的eBPF程序中LPM map的键结构完全一致):

// LPMKey 对应IPv4 LPM trie的键结构
type LPMKey struct {
    PrefixLen uint32 // 前缀长度,比如/32对应值为32
    IP        [4]byte // IPv4地址的字节数组
}

第二步:将CIDR字符串转换为LPMKey切片

写一个工具函数,把传入的CIDR列表转换成Batch API需要的键格式:

import "net"

func cidrsToLPMKeys(cidrs []string) ([]LPMKey, error) {
    var keys []LPMKey
    for _, cidr := range cidrs {
        ipNet, err := net.ParseCIDR(cidr)
        if err != nil {
            return nil, err
        }
        
        // 提取CIDR前缀长度
        prefixLen, _ := ipNet.Mask.Size()
        // 将IPv4地址转换为[4]byte格式
        var ipBytes [4]byte
        copy(ipBytes[:], ipNet.IP.To4())
        
        keys = append(keys, LPMKey{
            PrefixLen: uint32(prefixLen),
            IP:        ipBytes,
        })
    }
    return keys, nil
}

第三步:替换原有单条更新逻辑为BatchUpdate

原来的代码是循环调用Update逐个添加IP,现在用Batch方法批量操作:

import "github.com/cilium/ebpf"
import "log"

func main() {
    // 假设你已经完成LPM map的初始化(变量名lpmMap)
    // 你的黑名单IP列表
    denyIPs := []string{"10.11.15.114/32", "127.0.0.1/32"}
    
    // 转换为LPM键切片
    lpmKeys, err := cidrsToLPMKeys(denyIPs)
    if err != nil {
        log.Fatalf("转换CIDR失败: %v", err)
    }
    
    // 构建批量更新条目
    var batchEntries []ebpf.BatchEntry
    for _, key := range lpmKeys {
        batchEntries = append(batchEntries, ebpf.BatchEntry{
            Key:   &key,
            Value: &struct{}{}, // 替换成你实际需要存储的值类型(比如xdp-firewall中的bool类型)
            Op:    ebpf.BatchUpdate, // 指定操作为更新
        })
    }
    
    // 执行批量更新
    successCount, err := lpmMap.Batch(batchEntries, nil)
    if err != nil {
        log.Fatalf("批量更新失败: %v,已成功执行%d条", err, successCount)
    }
}

第四步:批量删除IP(BatchDelete)

如果需要批量移除黑名单IP,只需要修改Op为ebpf.BatchDelete即可:

// 构建批量删除条目
var deleteBatch []ebpf.BatchEntry
for _, key := range lpmKeys {
    deleteBatch = append(deleteBatch, ebpf.BatchEntry{
        Key:   &key,
        Op:    ebpf.BatchDelete, // 指定操作为删除
    })
}

// 执行批量删除
successCount, err := lpmMap.Batch(deleteBatch, nil)
if err != nil {
    log.Fatalf("批量删除失败: %v,已成功执行%d条", err, successCount)
}

注意事项

  • 确保Go侧的LPMKey结构体和eBPF程序中LPM map的键定义完全一致(字段顺序、类型、字节序),否则会导致操作失败
  • Batch方法返回的successCount是已经成功执行的条目数,即使部分失败也会返回这个值,你可以根据需求做重试或部分处理
  • 第三个参数可以传入ebpf.BatchOptions设置超时等参数,默认传nil使用配置

内容的提问来源于stack exchange,提问作者99Linux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:10:26