OVS代码笔记
>> 原创文章,转载请保留地址,欢迎交流学习
- ovsdb-client:
从main开始分析:
1、for (command = get_all_commands(); ; command++) {
if (!command->name) {
VLOG_FATAL("unknown command '%s'; use --help for help",
argv[optind]);
} else if (!strcmp(command->name, argv[optind])) {
break;
}
}
获取ovsdb-client的相关的cmd操作的指针command,为后面的命令参数操作和命令实际操作函数handler做准备;这里的get_all_commands比较简单就不展开分析了;
2、if (command->need != NEED_NONE) {
if (argc - optind > command->min_args
&& (isalpha((unsigned char) argv[optind][0])
&& strchr(argv[optind], ':'))) {
rpc = open_jsonrpc(argv[optind++]);
} else {
char *sock = xasprintf("unix:%s/db.sock", ovs_rundir());
rpc = open_jsonrpc(sock);
free(sock);
}
} else {
rpc = NULL;
}
这段代码的主要作用就是根据SERVER参数返回rpc(一般默认的SERVER的参数为unix:/usr/local/var/run/openvswitch/db.sock);该数据结构如下:
struct jsonrpc {
struct stream *stream;
char *name;
int status;
/* Input. */
struct byteq input;
uint8_t input_buffer[512];
struct json_parser *parser;
/* Output. */
struct ovs_list output; /* Contains "struct ofpbuf"s. */
size_t output_count; /* Number of elements in "output". */
size_t backlog;
};
其中比较重要的几个部分是:
- stream,该指针通过函数jsonrpc_stream_open来实现其返回值;具体的做法是通过SERVER的名字查找到之前就定义好的stream class(这里默认的是unix_stream_class),然后用定义好的该stream class的open函数去填充stream中的内容,包括它自己的stream class(注意这里的stream class被修改为了stream_fd_class,后续会利用该stream class中的内容去处理stream信息),填充name为SERVER,至此,stream的相关的处理就完成了(这里仍然有部分细节还需要再分析);
- 得到了stream之后,再使用jsonrpc_open函数去根据stream得到这里比较重要的jsonrpc信息;具体的做法是新分配一个jsonrpc结构体,然后使用a中的stream来初始化jsonrpc中的stream和name信息,然后再初始化input和output相关的信息;
- if (command->need == NEED_DATABASE) {
struct svec dbs;
svec_init(&dbs);
fetch_dbs(rpc, &dbs);
if (argc - optind > command->min_args
&& svec_contains(&dbs, argv[optind])) {
database = argv[optind++];
} else if (dbs.n == 1) {
database = xstrdup(dbs.names[0]);
} else if (svec_contains(&dbs, "Open_vSwitch")) {
database = "Open_vSwitch";
} else {
ovs_fatal(0, "no default database for `%s' command, please "
"specify a database name", command->name);
}
svec_destroy(&dbs);
} else {
database = NULL;
}
if (argc - optind < command->min_args ||
argc - optind > command->max_args) {
VLOG_FATAL("invalid syntax for '%s' (use --help for help)",
command->name);
}
command->handler(rpc, database, argc - optind, argv + optind);
jsonrpc_close(rpc);
该段流程主要是完成了database的命名,并且根据相关的参数信息去完成handler的操作,该操作的主要调用流程可以查看all_commands命令的的处理(这里涉及到的细节较多,可以等待分析各个操作的时候再来分析);
- Ovsdb_server:
shash_find_data(const struct shash *sh, const char *name):根据DATABASE-NAME查找出来ovsdb;
关注shash_node和shash之间的关系以及它们如何关联起来?
server_config结构:
struct server_config {
struct sset *remotes;
struct shash *all_dbs;
FILE *config_tmpfile;
struct ovsdb_jsonrpc_server *jsonrpc;
};
下面以server的main函数为例说明:
Remotes:存放DB相关的参数,其实主要存储了DB的name,以hash方式存储;
All_dbs:将结构体db(该结构体在ovsdb_file_open函数中做好了实例化操作)作为hash参数放入到其中,以hash方式存储;
Config_tmpfile:存放DB相关的参数的临时文件,包括了remotes和dbfilename;
Jsonrpc:存放被server服务的DB,最后将上面的db结构中的ovsdb结构体放入到jsonrpc->up.dbs中,以hash方式存储;另外其中的remotes存放的是ovsdb_jsonrpc_remote结构,以hash方式存储在node下的data中;
除此之外,还有一个比较重要的函数处理:reconfigure_remotes,它的第一个作用是将之前处理好的all_dbs中的数据库相关的数据获取出来并放入另外一个类似的临时结构中(该数据库的内容以hash方式存放在其中,这里比较不理解的是,在查找hash的过程中,返回来的void值都是以ovsdb_jsonrpc_options指针的形式返回的?其他的疑问为此处以数据库的内容为hash方式向hash中存放的是ovsdb_jsonrpc_options结构?该结构中并没有什么数据,最终以shash_node方式呈现,name存放的就是string类型的数据的内容,data存放的就是之前的ovsdb_jsonrpc_options结构。);另外一个作用是配置ovsdb_jsonrpc_server中的remotes项,该remotes以hash方式存放在node下的data中,数据内容为ovsdb_jsonrpc_remote结构;
Ovsdb_jsonrpc_remote结构:
struct ovsdb_jsonrpc_remote {
struct ovsdb_jsonrpc_server *server;
struct pstream *listener; /* Listener, if passive. */
struct ovs_list sessions; /* List of "struct ovsdb_jsonrpc_session"s. */
uint8_t dscp;
};
Server:该结构和ovsdb_jsonrpc_remote相互关联,首先该结构和ovsdb_jsonrpc_remote中的server是同一块区域,其次ovsdb_jsonrpc_remote结构会以void *data的形式添加到ovsdb_jsonrpc_server的remotes哈希map结构的节点中;
Listener:跟我们的连接的方式(ptcp、punix、pssl等)有关系的一个pstream变量,该变量和client获取的方式类似;
Sessions:ovsdb_jsonrpc_sessions结构的链表,将ovsdb_jsonrpc_session中的node节点插入到该链表中;
Ovsdb_jsonrpc_server结构:
struct ovsdb_jsonrpc_server {
struct ovsdb_server up;
unsigned int n_sessions, max_sessions;
struct shash remotes; /* Contains "struct ovsdb_jsonrpc_remote *"s. */
};
up:目前没有发现该结构体的用途,因为只有初始化了,但是实际并没有做赋值操作,在注释中显示的是跟ovsdb关联的数据结构体(该结构的实际用途就是将ovsdb结构以hash方式存储在该ovsdb_server中,参见上面的server_config结构的说明);
n_sessions, max_sessions:表示了连接的数量和最多连接的数量;
remotes:该结构用来以哈希方式存储ovsdb_jsonrpc_remote的结构,可以参见上面的ovsdb_jsonrpc_remote结构的描述;
Ovsdb_server结构:
struct ovsdb_server {
struct shash dbs; /* Maps from a db name to a "struct ovsdb *". */
struct hmap locks; /* Contains "struct ovsdb_lock"s indexed by name. */
};
dbs:暂时没有发现什么用途;
locks:暂时没有发现什么用途;
Ovsdb_jsonrpc_session结构:
struct ovsdb_jsonrpc_session {
struct ovs_list node; /* Element in remote's sessions list. */
struct ovsdb_session up;
struct ovsdb_jsonrpc_remote *remote;
/* Triggers. */
struct hmap triggers; /* Hmap of "struct ovsdb_jsonrpc_trigger"s. */
/* Monitors. */
struct hmap monitors; /* Hmap of "struct ovsdb_jsonrpc_monitor"s. */
/* Network connectivity. */
struct jsonrpc_session *js; /* JSON-RPC session. */
unsigned int js_seqno; /* Last jsonrpc_session_get_seqno() value. */
};
node:该节点为remote session的元素,最终该节点会被挂接到ovsdb_jsonrpc_remote结构中的sessions中去;
up:该结构和ovsdb_server类似,只是该节点表示client;
remote:该结构和ovsdb_jsonrpc_remote关联起来;
triggers:ovsdb_jsonrpc_trigger结构体的hash map;
monitors:ovsdb_jsonrpc_monitor结构体的hash map;
js:jsonrpc的session,该结构会和初始化好的jsonrpc_session关联起来;
js_seqno:用于存储上次的jsonrpc_session_get_seqno值,初始化时为0;
Jsonrpc_session结构:
struct jsonrpc_session {
struct reconnect *reconnect;
struct jsonrpc *rpc;
struct stream *stream;
struct pstream *pstream;
int last_error;
unsigned int seqno;
uint8_t dscp;
};
reconnect:暂时不知道用途;
rpc:jsonrpc相关的结构,该结构会在client中进行描述说明;
stream:active stream connection相关的结构;
pstream:passive listener相关的结构;
last_error:应该是用于错误信息,暂时不知道其用途;
seqno:用于存储上次的jsonrpc_session_get_seqno值,初始化时为0;
sdcp:暂时不知道其用途;
Ovsdb_session结构:
struct ovsdb_session {
struct ovsdb_server *server;
struct ovs_list completions;/* Completed triggers. */
struct hmap waiters; /* "ovsdb_lock_waiter *"s by lock name. */
};
server:该结构会和ovsdb_jsonrpc_server中的ovsdb_server关联起来;
completions:从注释来看用于trigger的链表,暂时没有发现用途;
waiters:从注释来看用于ovsdb_lock_waiter的链表,暂时没有发现用途;
ovsdb结构:
struct ovsdb {
struct ovsdb_schema *schema;
struct ovs_list replicas; /* Contains "struct ovsdb_replica"s. */
struct shash tables; /* Contains "struct ovsdb_table *"s. */
/* Triggers. */
struct ovs_list triggers; /* Contains "struct ovsdb_trigger"s. */
bool run_triggers;
};
Schema:database schema结构;
Replicas:用于处理ovsdb_replica的链表;
Tables:用于处理ovsdb_table的hash;
Triggers:用于处理ovsdb_trigger的链表;
Run_trigger:运行trigger标志位;
Ovsdb_schema结构:
/* Database schema. */
struct ovsdb_schema {
char *name;
char *version;
char *cksum;
struct shash tables; /* Contains "struct ovsdb_table_schema *"s. */
};