3.bridge,ofproto模块是vswitchd的核心,启动的时候初始化网桥(OVSDB配置相关),接着依次运行RPC服务,网桥,网络设备相关的调用。
----------vswitchd/ovs-vswitchd.c
bridge_init(remote);
free(remote);
exiting = false;
while (!exiting) {
worker_run();
bridge_run_fast();
bridge_run();
bridge_run_fast();
unixctl_server_run(unixctl);
netdev_run();
............
free(remote);
exiting = false;
while (!exiting) {
worker_run();
bridge_run_fast();
bridge_run();
bridge_run_fast();
unixctl_server_run(unixctl);
netdev_run();
............
---------lib/worker.c
3.1 如果该进程启动了一个worker(client_sock >= 0)并且没有发生故障,调用reply_cb来回复。其实就相当于多线程,时刻待命响应主进程的各种请求。
void worker_run(void){
if (worker_is_running()) {
int error;
error = rxbuf_run(&client_rx, client_sock, sizeof(struct worker_reply));
if (!error) {
struct worker_reply *reply = client_rx.header.data;
reply->reply_cb(&client_rx.payload, client_rx.fds, client_rx.n_fds, reply->reply_aux);
rxbuf_clear(&client_rx);
} else if (error != EAGAIN) {
worker_broke();
VLOG_ABORT("receive from worker failed (%s)",
ovs_retval_to_string(error));
}
}
}
if (worker_is_running()) {
int error;
error = rxbuf_run(&client_rx, client_sock, sizeof(struct worker_reply));
if (!error) {
struct worker_reply *reply = client_rx.header.data;
reply->reply_cb(&client_rx.payload, client_rx.fds, client_rx.n_fds, reply->reply_aux);
rxbuf_clear(&client_rx);
} else if (error != EAGAIN) {
worker_broke();
VLOG_ABORT("receive from worker failed (%s)",
ovs_retval_to_string(error));
}
}
}
3.2 函数 bridge_run_fast执行间歇性的活动:遍历所有的网桥,然后完成of switch的功能(通过bridge->ofproto)。在每次轮询循环中多次呼叫这个函数很有意义,因为ofprotos使用ofproto-dpif 实现,可以有性能提升。
函数 bridge_run 通过和ovsdb的沟通维护一些系统状态,核心逻辑仍然是通过ofproto完成相应的任务。
void bridge_run_fast(void) {
struct bridge *br;
HMAP_FOR_EACH (br, node, &all_bridges) {
ofproto_run_fast(br->ofproto);
}
}
void bridge_run(void) {
static const struct ovsrec_open_vswitch null_cfg;
const struct ovsrec_open_vswitch *cfg;
struct ovsdb_idl_txn *reconf_txn = NULL;
bool vlan_splinters_changed;
struct bridge *br;
ovsrec_open_vswitch_init((struct ovsrec_open_vswitch *) &null_cfg);
/* (Re)configure if necessary. */
if (!reconfiguring) {
ovsdb_idl_run(idl);
if (ovsdb_idl_is_lock_contended(idl)) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
struct bridge *br, *next_br;
VLOG_ERR_RL(&rl, "another ovs-vswitchd process is running, disabling this process until it goes away");
HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
bridge_destroy(br);
}
return;
} else if (!ovsdb_idl_has_lock(idl)) {
return;
}
}
cfg = ovsrec_open_vswitch_first(idl);
/* Let each bridge do the work that it needs to do. */
HMAP_FOR_EACH (br, node, &all_bridges) {
ofproto_run(br->ofproto);
}
/* 重新配置SSL,选择在主循环中而不是在数据库改变的时候配置ssl,是因为在没有数据库改变的情况下key和certificate文件内容也会改变;选择在 bridge_reconfigure()之前是因为这个函数可能需要初始化SSL连接(需要配置SSL)。 */
struct bridge *br;
HMAP_FOR_EACH (br, node, &all_bridges) {
ofproto_run_fast(br->ofproto);
}
}
void bridge_run(void) {
static const struct ovsrec_open_vswitch null_cfg;
const struct ovsrec_open_vswitch *cfg;
struct ovsdb_idl_txn *reconf_txn = NULL;
bool vlan_splinters_changed;
struct bridge *br;
ovsrec_open_vswitch_init((struct ovsrec_open_vswitch *) &null_cfg);
/* (Re)configure if necessary. */
if (!reconfiguring) {
ovsdb_idl_run(idl);
if (ovsdb_idl_is_lock_contended(idl)) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
struct bridge *br, *next_br;
VLOG_ERR_RL(&rl, "another ovs-vswitchd process is running, disabling this process until it goes away");
HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
bridge_destroy(br);
}
return;
} else if (!ovsdb_idl_has_lock(idl)) {
return;
}
}
cfg = ovsrec_open_vswitch_first(idl);
/* Let each bridge do the work that it needs to do. */
HMAP_FOR_EACH (br, node, &all_bridges) {
ofproto_run(br->ofproto);
}
/* 重新配置SSL,选择在主循环中而不是在数据库改变的时候配置ssl,是因为在没有数据库改变的情况下key和certificate文件内容也会改变;选择在 bridge_reconfigure()之前是因为这个函数可能需要初始化SSL连接(需要配置SSL)。 */
if (cfg && cfg->ssl) {
const struct ovsrec_ssl *ssl = cfg->ssl;
stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
}
if (!reconfiguring) {
/* If VLAN splinters are in use, then we need to reconfigure if VLAN usage has changed. */
vlan_splinters_changed = false;
if (vlan_splinters_enabled_anywhere) {
HMAP_FOR_EACH (br, node, &all_bridges) {
if (ofproto_has_vlan_usage_changed(br->ofproto)) {
vlan_splinters_changed = true;
break;
}
}
}
if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed) {
idl_seqno = ovsdb_idl_get_seqno(idl);
if (cfg) {
reconf_txn = ovsdb_idl_txn_create(idl);
bridge_reconfigure(cfg);
} else {
/* We still need to reconfigure to avoid dangling pointers to
* now-destroyed ovsrec structures inside bridge data. */
bridge_reconfigure(&null_cfg);
}
}
}
if (reconfiguring) {
if (cfg) {
if (!reconf_txn) {
reconf_txn = ovsdb_idl_txn_create(idl);
}
if (bridge_reconfigure_continue(cfg)) {
ovsrec_open_vswitch_set_cur_cfg(cfg, cfg->next_cfg);
}
} else {
bridge_reconfigure_continue(&null_cfg);
}
}
if (reconf_txn) {
ovsdb_idl_txn_commit(reconf_txn);
ovsdb_idl_txn_destroy(reconf_txn);
reconf_txn = NULL;
}
/* Refresh interface and mirror stats if necessary. */
if (time_msec() >= iface_stats_timer) {
if (cfg) {
struct ovsdb_idl_txn *txn;
txn = ovsdb_idl_txn_create(idl);
HMAP_FOR_EACH (br, node, &all_bridges) {
struct port *port;
struct mirror *m;
HMAP_FOR_EACH (port, hmap_n
const struct ovsrec_ssl *ssl = cfg->ssl;
stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate);
stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
}
if (!reconfiguring) {
/* If VLAN splinters are in use, then we need to reconfigure if VLAN usage has changed. */
vlan_splinters_changed = false;
if (vlan_splinters_enabled_anywhere) {
HMAP_FOR_EACH (br, node, &all_bridges) {
if (ofproto_has_vlan_usage_changed(br->ofproto)) {
vlan_splinters_changed = true;
break;
}
}
}
if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed) {
idl_seqno = ovsdb_idl_get_seqno(idl);
if (cfg) {
reconf_txn = ovsdb_idl_txn_create(idl);
bridge_reconfigure(cfg);
} else {
/* We still need to reconfigure to avoid dangling pointers to
* now-destroyed ovsrec structures inside bridge data. */
bridge_reconfigure(&null_cfg);
}
}
}
if (reconfiguring) {
if (cfg) {
if (!reconf_txn) {
reconf_txn = ovsdb_idl_txn_create(idl);
}
if (bridge_reconfigure_continue(cfg)) {
ovsrec_open_vswitch_set_cur_cfg(cfg, cfg->next_cfg);
}
} else {
bridge_reconfigure_continue(&null_cfg);
}
}
if (reconf_txn) {
ovsdb_idl_txn_commit(reconf_txn);
ovsdb_idl_txn_destroy(reconf_txn);
reconf_txn = NULL;
}
/* Refresh interface and mirror stats if necessary. */
if (time_msec() >= iface_stats_timer) {
if (cfg) {
struct ovsdb_idl_txn *txn;
txn = ovsdb_idl_txn_create(idl);
HMAP_FOR_EACH (br, node, &all_bridges) {
struct port *port;
struct mirror *m;
HMAP_FOR_EACH (port, hmap_n