ovsdb<9> client server 代码流程

mac2026-08-30  13

4.4.1 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;

}; 其中比较重要的几个部分是: a、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的相关的处理就完成了(这里仍然有部分细节还需要再分析); b、得到了stream之后,再使用jsonrpc_open函数去根据stream得到这里比较重要的jsonrpc信息;具体的做法是新分配一个jsonrpc结构体,然后使用a中的stream来初始化jsonrpc中的stream和name信息,然后再初始化input和output相关的信息;

3、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命令的的处理(这里涉及到各个操作的详细处理,主要就是对数据库发送request操作,具体的流程都是类似的,就不再展开说明);

4.4.2 ovsdb-server流程 1、初始化server_config信息 sset_init(&db_filenames); if (argc > 0) { for (i = 0; i < argc; i++) { sset_add(&db_filenames, argv[i]); } } else { char *default_db = xasprintf("%s/conf.db", ovs_dbdir()); sset_add(&db_filenames, default_db); free(default_db); }

server_config.remotes = &remotes; server_config.config_tmpfile = config_tmpfile; save_config__(config_tmpfile, &remotes, &db_filenames); daemonize_start(false); /* Load the saved config. */ load_config(config_tmpfile, &remotes, &db_filenames); jsonrpc = ovsdb_jsonrpc_server_create(); shash_init(&all_dbs); server_config.all_dbs = &all_dbs; server_config.jsonrpc = jsonrpc;

该部分主要是初始化了server_config中的remotes、all_dbs、config_tmpfile和jsonrpc等变量;

2、读取ovsdb数据并将读取的数据放入all_dbs和jsonrpc.up中 SSET_FOR_EACH (db_filename, &db_filenames) { error = open_db(&server_config, db_filename); if (error) { ovs_fatal(0, “%s”, error); } }

3、配置jsonrpc error = reconfigure_remotes(jsonrpc, &all_dbs, &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结构;

4、进入主循环操作 main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting); 这里省略了部分细节,将大致流程描述如下: ovsdb_jsonrpc_server_run-> ovsdb_jsonrpc_session_run_all-> ovsdb_jsonrpc_session_run-> ovsdb_jsonrpc_session_got_request 这里主要是等待client发送jsonrpc消息过来,然后根据消息对ovsdb进行相应的处理并对client回应result。

最新回复(0)