亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原(yuan)創

DPDK的rte bpf分析

2024-08-02 09:34:14
96
0

1、dpdk的bpf組件

dpdk提供了一個bpf的(de)組件,編譯成功后是librte_bpf.so/librte_bpf.a,以一個單獨的(de)庫呈現。

特點:

1、可以不依(yi)賴于(yu)dpdk初(chu)始化,直接使用

2、用戶自定義eBPF helper函(han)數(shu)

3、支持arm和(he)x86下的JIT

4、支持eBPF validate

5、支持rte mbuf

6、支持在rx/tx流程(cheng)的處理

7、eBPF程序(xu)入口(kou)支持一(yi)個參數(void *)

不足之處:

1、不支持尾(wei)調(diao)用,即(ji)ebpf程序不能互相調(diao)用

2、API接口分析

2.1 結構體

//bpf主要的結構體信息
/**
 * Possible types for function/BPF program arguments.
 */
enum rte_bpf_arg_type {
	RTE_BPF_ARG_UNDEF,      /**< undefined */
	RTE_BPF_ARG_RAW,        /**< scalar value */
	RTE_BPF_ARG_PTR = 0x10, /**< pointer to data buffer */
	RTE_BPF_ARG_PTR_MBUF,   /**< pointer to rte_mbuf */
	RTE_BPF_ARG_RESERVED    /**< reserved for internal use */
};

/**
 * function argument information
 */
struct rte_bpf_arg {
	enum rte_bpf_arg_type type;
	/**
	 * for ptr type - max size of data buffer it points to
	 * for raw type - the size (in bytes) of the value
	 */
	size_t size;  /* type = RTE_BPF_ARG_PTR時,size = BUF大小 */
	size_t buf_size;
	/**< for mbuf ptr type, max size of rte_mbuf data buffer */
};

/**
 * Possible types for external symbols.
 */
enum rte_bpf_xtype {
	RTE_BPF_XTYPE_FUNC, /**< function */
	RTE_BPF_XTYPE_VAR   /**< variable */
};

/**
 * Definition for external symbols available in the BPF program.
 */
/*
描述eBPF helper的結構體,分為兩種:
1、全局變量:當eBPF程序使用全局變量時,需要定義,但是一般不建議使用全局變量
2、函數:elf文件的 rel section中描述的函數。
*/
struct rte_bpf_xsym {
	const char *name;        /**< name */   /* elf文件的 rel section中描述的函數的名稱 */
	enum rte_bpf_xtype type; /**< type */
	union {
		struct {
			uint64_t (*val)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);    /* eBPF helper 函數 */
			uint32_t nb_args;
			struct rte_bpf_arg args[EBPF_FUNC_MAX_ARGS];
			/**< Function arguments descriptions. */
			struct rte_bpf_arg ret; /**< function return value. */
		} func;
		struct {
			void *val; /**< actual memory location */
			struct rte_bpf_arg desc; /**< type, size, etc. */
		} var; /**< external variable */
	};
};

/**
 * Input parameters for loading eBPF code.
 */
struct rte_bpf_prm {
	const struct ebpf_insn *ins; /**< array of eBPF instructions */   //eBPF 字節碼
	uint32_t nb_ins;            /**< number of instructions in ins */
	const struct rte_bpf_xsym *xsym;           //eBPF helper函數
	/**< array of external symbols that eBPF code is allowed to reference */
	uint32_t nb_xsym; /**< number of elements in xsym */
	struct rte_bpf_arg prog_arg; /**< eBPF program input arg description */ //eBPF程序的入口參數的描述
};

/**
 * Information about compiled into native ISA eBPF code.
 */
struct rte_bpf_jit {
	uint64_t (*func)(void *); /**< JIT-ed native code */   //eBPF程序的入口
	size_t sz;                /**< size of JIT-ed code */
};

/*  
rte bpf的主體
*/
struct rte_bpf {
	struct rte_bpf_prm prm;   //eBPF字節碼等信息
	struct rte_bpf_jit jit;      //JIT
	size_t sz;        // sizeof(struct rte_bpf) + n_xsym * sizeof(struct rte_bpf_xsym) + n * sizeof(struct ebpf_insn)
	uint32_t stack_sz;   //
};

2.2 RX/TX收發包流程的接口( rte_bpf_ethdev.h )

前置(zhi):需(xu)使用dpdk進行(xing)收(shou)發包,才能使用。

(1)RX/TX加載eBPF的(de)接口

int rte_bpf_eth_rx_elf_load(uint16_t port, uint16_t queue, const struct rte_bpf_prm *prm, const char *fname, const char *sname, uint32_t flags);

int rte_bpf_eth_tx_elf_load(uint16_t port, uint16_t queue, const struct rte_bpf_prm *prm, const char *fname, const char *sname, uint32_t flags);

參數:

port 端口
queue 隊列
prm eBPF的helper函數
fname elf文件路徑
sname elf文件的可執行區域
flags 預期執行eBPF的方法(JIT和非eBPF編碼)

流程:

rte_bpf_eth_rx/tx_elf_load()
    ->bpf_eth_elf_load()
        ->select_rx_callback() /select_tx_callback() //根據 flags 和 eBPF程序入口參數類型,選擇rx和tx的回調函數
        ->rte_bpf_elf_load() // 解析elf文件,翻譯為eBPF字節碼,做validate和JIT,得到eBPF , 見下文
        ->rte_bpf_get_jit() //通過bpf獲取JIT
        ->bpf_eth_cbh_add() //根據port和queue 使能callback
        ->rte_eth_add_rx_callback() / rte_eth_add_tx_callback() //根據port id和queue id將callback掛在對應的收發包回調上

(2)RX/TX卸載(zai)eBPF的接口(kou)

void rte_bpf_eth_rx_unload(uint16_t port, uint16_t queue);

void rte_bpf_eth_tx_unload(uint16_t port, uint16_t queue);

參(can)數:

port 端口號
queue 隊列號

流程:

rte_bpf_eth_rx/tx_unload()
    ->bpf_eth_cbh_find() // 根據port和queue找到掛載點
    ->rte_eth_remove_rx_callback() / rte_eth_remove_tx_callback() //從rx和tx上卸載callback
    ->bpf_eth_cbi_unload() //刪除掛載點

(3)call流程

rte_eth_rx_burst() / rte_eth_tx_burst()
     -> rte_eth_call_rx_callbacks()
           ->cb->fn.rx() / cb->fn.tx()  // 執行select_tx/rx_callback()的函數

2.3、 generic API (rte_bpf.h)

(1)加載eBPF的接(jie)口

struct rte_bpf * rte_bpf_load(const struct rte_bpf_prm *prm);  //通過prm得到bpf

備注:此接(jie)口需(xu)要填充(chong)好prm的(de)所有信息(eBPF字節碼,eBPF helper函數、eBPF程(cheng)序(xu)入口參(can)數的(de)描述)

流程見下文:

struct rte_bpf * rte_bpf_elf_load(const struct rte_bpf_prm *prm, const char *fname,  const char *sname);

參數:

prm eBPF helper 函數、eBPF程序入口參數的描述
fname elf文件路徑
sname elf文件的可執行區域

流程:

rte_bpf_elf_load()
    ->open()  //根據 fname 打開elf文件
    ->bpf_load_elf()
        ->find_elf_code() //根據sname 找到elf文件的可執行區域
        ->elf_reloc_code() //do relocation 即將eBPF程序引用的外部函數(可以理解為庫函數)替換為eBPF helper 函數
        ->rte_bpf_load()  //此時已經將elf文件轉換為了eBPF字節碼

rte_bpf_load()
    ->bpf_check_xsym()  //校驗eBPF helper 函數是否合規
    ->bpf_load() //mmap 申請內存,得到struct rte bpf
    ->__rte_bpf_validate()  //eBPF validate
    ->__rte_bpf_jit()  // JIT

//可以修改rte_bpf_elf_load() 函數,只做將elf文件翻譯為eBPF字節碼。在不要求性能的情況下直接使用eBPF字節碼

 

(2)執行eBPF的接口(kou)

uint64_t rte_bpf_exec(const struct rte_bpf *bpf, void *ctx);   //執行指定的context

uint32_t rte_bpf_exec_burst(const struct rte_bpf *bpf, void *ctx[], uint64_t rc[], uint32_t num);  //同一(yi)(yi)個eBPF程序,執(zhi)行一(yi)(yi)組context

備注(zhu):這兩個接口是直(zhi)接執行eBPF字節碼的(de)接口,在不要求(qiu)性能的(de)情況(kuang)下可(ke)以使(shi)(shi)用(yong),要求(qiu)性能時(shi)使(shi)(shi)用(yong)JIT

參數:

bpf eBPF程序
ctx eBPF程序入口的參數

流程:

rte_bpf_exec

rte_bpf_exec()
     ->rte_bpf_exec_burst() 
     ->bpf_exec()   //直接執行eBPF字節碼

 

int rte_bpf_get_jit(const struct rte_bpf *bpf, struct rte_bpf_jit *jit);   //執行JIT程序。

參數:

bpf eBPF程序
jit 出參,得到JIT
rte_bpf_get_jit(const struct rte_bpf *bpf, struct rte_bpf_jit *jit)
{
	if (bpf == NULL || jit == NULL)
		return -EINVAL;

	jit[0] = bpf->jit;
	return 0;
}
拿到JIT后,運行 jit.func 即可

 

(3)銷毀eBPF的接口

void&nbsp;rte_bpf_destroy(struct rte_bpf *bpf);  // 接(jie)口(kou)會銷毀bpf和jit

rte_bpf_destroy(struct rte_bpf *bpf)
{
	if (bpf != NULL) {
		if (bpf->jit.func != NULL)
			munmap(bpf->jit.func, bpf->jit.sz);
		munmap(bpf, bpf->sz);
	}
}
0條評論
0 / 1000
z****n
10文章數
1粉絲數
z****n
10 文章(zhang) | 1 粉絲
原(yuan)創(chuang)

DPDK的rte bpf分析

2024-08-02 09:34:14
96
0

1、dpdk的bpf組件

dpdk提(ti)供了一個bpf的組件,編(bian)譯成功后是librte_bpf.so/librte_bpf.a,以(yi)一個單獨的庫呈現(xian)。

特點:

1、可(ke)以不依賴于dpdk初(chu)始化,直接使用

2、用戶(hu)自定義eBPF helper函數

3、支持arm和(he)x86下的JIT

4、支持eBPF validate

5、支(zhi)持rte mbuf

6、支持在(zai)rx/tx流程的(de)處理

7、eBPF程序入口支持一(yi)個參數(void *)

不足之處:

1、不(bu)支持尾調(diao)用(yong)(yong),即ebpf程(cheng)序不(bu)能互相調(diao)用(yong)(yong)

2、API接口分析

2.1 結構體

//bpf主要的結構體信息
/**
 * Possible types for function/BPF program arguments.
 */
enum rte_bpf_arg_type {
	RTE_BPF_ARG_UNDEF,      /**< undefined */
	RTE_BPF_ARG_RAW,        /**< scalar value */
	RTE_BPF_ARG_PTR = 0x10, /**< pointer to data buffer */
	RTE_BPF_ARG_PTR_MBUF,   /**< pointer to rte_mbuf */
	RTE_BPF_ARG_RESERVED    /**< reserved for internal use */
};

/**
 * function argument information
 */
struct rte_bpf_arg {
	enum rte_bpf_arg_type type;
	/**
	 * for ptr type - max size of data buffer it points to
	 * for raw type - the size (in bytes) of the value
	 */
	size_t size;  /* type = RTE_BPF_ARG_PTR時,size = BUF大小 */
	size_t buf_size;
	/**< for mbuf ptr type, max size of rte_mbuf data buffer */
};

/**
 * Possible types for external symbols.
 */
enum rte_bpf_xtype {
	RTE_BPF_XTYPE_FUNC, /**< function */
	RTE_BPF_XTYPE_VAR   /**< variable */
};

/**
 * Definition for external symbols available in the BPF program.
 */
/*
描述eBPF helper的結構體,分為兩種:
1、全局變量:當eBPF程序使用全局變量時,需要定義,但是一般不建議使用全局變量
2、函數:elf文件的 rel section中描述的函數。
*/
struct rte_bpf_xsym {
	const char *name;        /**< name */   /* elf文件的 rel section中描述的函數的名稱 */
	enum rte_bpf_xtype type; /**< type */
	union {
		struct {
			uint64_t (*val)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);    /* eBPF helper 函數 */
			uint32_t nb_args;
			struct rte_bpf_arg args[EBPF_FUNC_MAX_ARGS];
			/**< Function arguments descriptions. */
			struct rte_bpf_arg ret; /**< function return value. */
		} func;
		struct {
			void *val; /**< actual memory location */
			struct rte_bpf_arg desc; /**< type, size, etc. */
		} var; /**< external variable */
	};
};

/**
 * Input parameters for loading eBPF code.
 */
struct rte_bpf_prm {
	const struct ebpf_insn *ins; /**< array of eBPF instructions */   //eBPF 字節碼
	uint32_t nb_ins;            /**< number of instructions in ins */
	const struct rte_bpf_xsym *xsym;           //eBPF helper函數
	/**< array of external symbols that eBPF code is allowed to reference */
	uint32_t nb_xsym; /**< number of elements in xsym */
	struct rte_bpf_arg prog_arg; /**< eBPF program input arg description */ //eBPF程序的入口參數的描述
};

/**
 * Information about compiled into native ISA eBPF code.
 */
struct rte_bpf_jit {
	uint64_t (*func)(void *); /**< JIT-ed native code */   //eBPF程序的入口
	size_t sz;                /**< size of JIT-ed code */
};

/*  
rte bpf的主體
*/
struct rte_bpf {
	struct rte_bpf_prm prm;   //eBPF字節碼等信息
	struct rte_bpf_jit jit;      //JIT
	size_t sz;        // sizeof(struct rte_bpf) + n_xsym * sizeof(struct rte_bpf_xsym) + n * sizeof(struct ebpf_insn)
	uint32_t stack_sz;   //
};

2.2 RX/TX收發包流程的接口( rte_bpf_ethdev.h )

前置:需使(shi)用dpdk進(jin)行收發包,才(cai)能使(shi)用。

(1)RX/TX加載eBPF的接口

int rte_bpf_eth_rx_elf_load(uint16_t port, uint16_t queue, const struct rte_bpf_prm *prm, const char *fname, const char *sname, uint32_t flags);

int rte_bpf_eth_tx_elf_load(uint16_t port, uint16_t queue, const struct rte_bpf_prm *prm, const char *fname, const char *sname, uint32_t flags);

參數:

port 端口
queue 隊列
prm eBPF的helper函數
fname elf文件路徑
sname elf文件的可執行區域
flags 預期執行eBPF的方法(JIT和非eBPF編碼)

流程:

rte_bpf_eth_rx/tx_elf_load()
    ->bpf_eth_elf_load()
        ->select_rx_callback() /select_tx_callback() //根據 flags 和 eBPF程序入口參數類型,選擇rx和tx的回調函數
        ->rte_bpf_elf_load() // 解析elf文件,翻譯為eBPF字節碼,做validate和JIT,得到eBPF , 見下文
        ->rte_bpf_get_jit() //通過bpf獲取JIT
        ->bpf_eth_cbh_add() //根據port和queue 使能callback
        ->rte_eth_add_rx_callback() / rte_eth_add_tx_callback() //根據port id和queue id將callback掛在對應的收發包回調上

(2)RX/TX卸(xie)載eBPF的(de)接(jie)口

void rte_bpf_eth_rx_unload(uint16_t port, uint16_t queue);

void rte_bpf_eth_tx_unload(uint16_t port, uint16_t queue);

參數:

port 端(duan)口(kou)號
queue 隊列號

流程:

rte_bpf_eth_rx/tx_unload()
    ->bpf_eth_cbh_find() // 根據port和queue找到掛載點
    ->rte_eth_remove_rx_callback() / rte_eth_remove_tx_callback() //從rx和tx上卸載callback
    ->bpf_eth_cbi_unload() //刪除掛載點

(3)call流程

rte_eth_rx_burst() / rte_eth_tx_burst()
     -> rte_eth_call_rx_callbacks()
           ->cb->fn.rx() / cb->fn.tx()  // 執行select_tx/rx_callback()的函數

2.3、 generic API (rte_bpf.h)

(1)加(jia)載eBPF的(de)接口

struct rte_bpf * rte_bpf_load(const struct rte_bpf_prm *prm);  //通過(guo)prm得(de)到bpf

備注:此(ci)接口需要填充(chong)好prm的所有信息(eBPF字節(jie)碼,eBPF helper函數(shu)、eBPF程序入口參數(shu)的描(miao)述(shu))

流程見下文:

struct rte_bpf * rte_bpf_elf_load(const struct rte_bpf_prm *prm, const char *fname,  const char *sname);

參數:

prm eBPF helper 函數、eBPF程序入口參數的描述
fname elf文件路徑
sname elf文件的可執行區域

流程:

rte_bpf_elf_load()
    ->open()  //根據 fname 打開elf文件
    ->bpf_load_elf()
        ->find_elf_code() //根據sname 找到elf文件的可執行區域
        ->elf_reloc_code() //do relocation 即將eBPF程序引用的外部函數(可以理解為庫函數)替換為eBPF helper 函數
        ->rte_bpf_load()  //此時已經將elf文件轉換為了eBPF字節碼

rte_bpf_load()
    ->bpf_check_xsym()  //校驗eBPF helper 函數是否合規
    ->bpf_load() //mmap 申請內存,得到struct rte bpf
    ->__rte_bpf_validate()  //eBPF validate
    ->__rte_bpf_jit()  // JIT

//可以修改rte_bpf_elf_load() 函數,只做將elf文件翻譯為eBPF字節碼。在不要求性能的情況下直接使用eBPF字節碼

 

(2)執行eBPF的接口(kou)

uint64_t rte_bpf_exec(const struct rte_bpf *bpf, void *ctx);   //執行指定的context

uint32_t rte_bpf_exec_burst(const struct rte_bpf *bpf, void *ctx[], uint64_t rc[], uint32_t num);  //同一(yi)個eBPF程序,執(zhi)行(xing)一(yi)組context

備注:這兩個接(jie)口是直(zhi)接(jie)執行eBPF字節(jie)碼的接(jie)口,在不要(yao)求性能的情況下可以使用,要(yao)求性能時使用JIT

參數:

bpf eBPF程序
ctx eBPF程序入口的參數

流程:

rte_bpf_exec

rte_bpf_exec()
     ->rte_bpf_exec_burst() 
     ->bpf_exec()   //直接執行eBPF字節碼

 

int rte_bpf_get_jit(const struct rte_bpf *bpf, struct rte_bpf_jit *jit);   //執行JIT程序。

參數:

bpf eBPF程序
jit 出參,得到JIT
rte_bpf_get_jit(const struct rte_bpf *bpf, struct rte_bpf_jit *jit)
{
	if (bpf == NULL || jit == NULL)
		return -EINVAL;

	jit[0] = bpf->jit;
	return 0;
}
拿到JIT后,運行 jit.func 即可

 

(3)銷毀(hui)eBPF的(de)接口(kou)

void rte_bpf_destroy(struct rte_bpf *bpf);  // 接(jie)口會銷毀bpf和jit

rte_bpf_destroy(struct rte_bpf *bpf)
{
	if (bpf != NULL) {
		if (bpf->jit.func != NULL)
			munmap(bpf->jit.func, bpf->jit.sz);
		munmap(bpf, bpf->sz);
	}
}
文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0