日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

netlink怎么读_ovs源码阅读--netlink使用

發(fā)布時間:2025/3/20 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 netlink怎么读_ovs源码阅读--netlink使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

netlink

netlink socket是一種用于用戶態(tài)進程和內(nèi)核態(tài)進程之間的通信機制。它通過為內(nèi)核模塊提供一組特殊的API,并為用戶程序提供了一組標準的socket接口的方式,實現(xiàn)了全雙工的通訊連接。

特點:

雙向傳輸,異步通信

用戶空間中使用標準socket API

內(nèi)核空間中使用專門的API

支持多播

可由內(nèi)核端發(fā)起通信

支持32種協(xié)議類型

netlink僅支持32種協(xié)議類型,這在實際應用中可能并不足夠,因此產(chǎn)生了generic netlink(以下簡稱為genl),

generic netlink支持1023個子協(xié)議號,彌補了netlink協(xié)議類型較少的缺陷。

通信架構(gòu)

Netlink子系統(tǒng):所有g(shù)enl通信的基礎,Netlink子系統(tǒng)中收到的所有Generic類型的netlink數(shù)據(jù)都被送到genl總線上;從內(nèi)核發(fā)出的數(shù)據(jù)也經(jīng)由genl總線送至netlink子系統(tǒng),再打包送至用戶空間

Generic Netlink控制器:作為內(nèi)核的一部分,負責動態(tài)地分配genl通道(即genl family id),并管理genl任務,genl控制器是一個特殊的genl內(nèi)核用戶,它負責監(jiān)聽genl bus上的通信通道

genl通信建立在一系列的通信通道的基礎上,每個genl family對應多個通道,這些通道由genl控制器動態(tài)分配

相關(guān)結(jié)構(gòu)體

genl family

Generic Netlink是基于客戶端-服務端模型的通信機制,服務端注冊family(family是對genl服務的各項定義的集合),控制器和客戶端都通過已注冊的信息與服務端通信。

//genl_family主要字段

struct genl_family

{

unsigned intid;//family id

unsigned int hdrsize; //用戶自定議頭部長度

char name[GENL_NAMSIZ]; //family名,要求不同的family使用不同的名字

unsigned int version;//版本

unsigned int maxattr;//最大attr類型數(shù),使用netlink標準的attr來傳輸數(shù)據(jù)

genl_ops *ops;// 操作集合

};

genl_ops

定義了netlink family相關(guān)的操作

// genl_ops主要字段

struct genl_ops

{

u8 cmd;//命令名,用于識別genl_ops

unsigned int flags;//設置屬性

struct nla_policy *policy; //定義了attr規(guī)則,genl在觸發(fā)事件處理程序之前,會用其進行attr校驗

int (*doit)(struct sk_buff *skb, struct genl_info *info);

int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb);

};

doit:回調(diào)函數(shù),在generic netlink收到數(shù)據(jù)時觸發(fā),運行在進程上下文

dumpit:回調(diào)函數(shù),當genl_ops的flag標志被添加了NLM_F_DUMP以后,每次收到genl消息即會回觸發(fā)這個函數(shù)

dumpit與doit的區(qū)別是:dumpit的第一個參數(shù)skb不會攜帶從客戶端發(fā)來的數(shù)據(jù)。相反地,開發(fā)者應該在skb中填入需要傳給客戶端的數(shù)據(jù),skb中攜帶的數(shù)據(jù)會被自動送到客戶端。只要dumpit的返回值大于0,dumpit函數(shù)就會再次被調(diào)用,并被要求在skb中填入數(shù)據(jù)。當服務端沒有數(shù)據(jù)要傳給客戶端時,dumpit要返回0。如果函數(shù)中出錯,要求返回一個負值。

nal_policy

定義了attr規(guī)則

struct nla_policy

{

u16 type;//attr中的數(shù)據(jù)類型

u16 len;//如果在type字段配置的是字符串有關(guān)的值,要把len設置為字符串的最大長度

};

genl_info

內(nèi)核在接收到用戶的genetlink消息后,會對消息解析并封裝成genl_info結(jié)構(gòu)

struct genl_info

{

u32 snd_seq; //發(fā)送序號

u32 snd_pid; //發(fā)送客戶端的PID

struct nlmsghdr * nlhdr; //netlink header的指針

struct genlmsghdr * genlhdr; //genl頭部的指針(即family頭部)

void * userhdr; //用戶自定義頭部指針

struct nlattr ** attrs; //如果定義了genl_ops->policy,保存被policy過濾以后的結(jié)果

};

Generic Netlink服務端(內(nèi)核)初始化

這里以OVS中packet的處理為例:

1. 定義family

//定義packet family

static struct genl_family dp_packet_genl_family __ro_after_init = {

.hdrsize = sizeof(struct ovs_header),

.name = OVS_PACKET_FAMILY,

.version = OVS_PACKET_VERSION,

.maxattr = OVS_PACKET_ATTR_MAX,

.netnsok = true,

.parallel_ops = true,

.ops = dp_packet_genl_ops, //操作集合

.n_ops = ARRAY_SIZE(dp_packet_genl_ops),

.module = THIS_MODULE,

};

2. 定義operation

// 定義packet family 的操作 --- packet類型的操作只支持OVS_PACKET_CMD_EXECUTE

static struct genl_ops dp_packet_genl_ops[] = {

{ .cmd = OVS_PACKET_CMD_EXECUTE,

.flags = GENL_UNS_ADMIN_PERM,

.policy = packet_policy,

.doit = ovs_packet_cmd_execute //接受數(shù)據(jù)包時,調(diào)用ovs_packet_cmd_execute進行處理

}

};

// 定義packet family 的過濾規(guī)則

static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = {

[OVS_PACKET_ATTR_PACKET] = { .len = ETH_HLEN },

[OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED },

[OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },

[OVS_PACKET_ATTR_PROBE] = { .type = NLA_FLAG },

[OVS_PACKET_ATTR_MRU] = { .type = NLA_U16 },

};

3. 注冊family

genl_register_family(&dp_packet_genl_family);

Generic Netlink客戶端(用戶空間)初始化

struct sockaddr_nl saddr;

int sock;

sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); //創(chuàng)建一個netlink類型的socket

if (sock < 0) {

return -1;

}

memset(&saddr, 0, sizeof(saddr));

saddr.nl_family = AF_NETLINK;

saddr.nl_pid = getpid();//獲取family id

if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {//綁定

printf("bind fail!\n");

close(*p_sock);

return -1;

}

內(nèi)核空間接受發(fā)送數(shù)據(jù)

接受數(shù)據(jù):內(nèi)核端一旦收到generic netlink數(shù)據(jù),會觸發(fā)doit函數(shù)運行,通過回調(diào)函數(shù)進行處理

發(fā)送數(shù)據(jù):將數(shù)據(jù)打包好之后,可通過單播(genlmsg_unicast)或多播()的形式進行發(fā)送

用戶空間接受發(fā)送數(shù)據(jù)

接受數(shù)據(jù):調(diào)用recv函數(shù)即可完成從內(nèi)核來的數(shù)據(jù)的接收

發(fā)送數(shù)據(jù):調(diào)用sendto來發(fā)送數(shù)據(jù)

netlink收發(fā)數(shù)據(jù)—以ovs中packet為例

參考內(nèi)容

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的netlink怎么读_ovs源码阅读--netlink使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。