这里先暂时记录下代码流程,有待完善。
static int construct(struct ofproto *ofproto_) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); const char *name = ofproto->up.name; int max_ports; int error; int i; error = dpif_create_and_open(name, ofproto->up.type, &ofproto->dpif); if (error) { VLOG_ERR("failed to open datapath %s: %s", name, strerror(error)); return error; } max_ports = dpif_get_max_ports(ofproto->dpif); ofproto_init_max_ports(ofproto_, MIN(max_ports, OFPP_MAX)); ofproto->n_matches = 0; dpif_flow_flush(ofproto->dpif); dpif_recv_purge(ofproto->dpif); // 设置'dpif'能够调用dpif_recv()来接收包 error = dpif_recv_set(ofproto->dpif, true); if (error) { VLOG_ERR("failed to listen on datapath %s: %s", name, strerror(error)); dpif_close(ofproto->dpif); return error; } ofproto->netflow = NULL; ofproto->sflow = NULL; ofproto->stp = NULL; hmap_init(&ofproto->bundles); ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME); for (i = 0; i < MAX_MIRRORS; i++) { ofproto->mirrors[i] = NULL; } ofproto->has_bonded_bundles = false; timer_set_duration(&ofproto->next_expiration, 1000); hmap_init(&ofproto->facets); hmap_init(&ofproto->subfacets); ofproto->governor = NULL; for (i = 0; i < N_TABLES; i++) { struct table_dpif *table = &ofproto->tables[i]; table->catchall_table = NULL; table->other_table = NULL; table->basis = random_uint32(); } ofproto->need_revalidate = 0; tag_set_init(&ofproto->revalidate_set); list_init(&ofproto->completions); ofproto_dpif_unixctl_init(); ofproto->has_mirrors = false; ofproto->has_bundle_action = false; hmap_init(&ofproto->vlandev_map); hmap_init(&ofproto->realdev_vid_map); hmap_insert(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node, hash_string(ofproto->up.name, 0)); memset(&ofproto->stats, 0, sizeof ofproto->stats); ofproto_init_tables(ofproto_, N_TABLES); error = add_internal_flows(ofproto); ofproto->up.tables[TBL_INTERNAL].flags = OFTABLE_HIDDEN | OFTABLE_READONLY; return error; }
设置dpif能够接收来自datapath的netlink包。
int dpif_recv_set(struct dpif *dpif, bool enable) { int error = dpif->dpif_class->recv_set(dpif, enable); log_operation(dpif, "recv_set", error); return error; }
static int dpif_linux_recv_set(struct dpif *dpif_, bool enable) { struct dpif_linux *dpif = dpif_linux_cast(dpif_); if ((dpif->epoll_fd >= 0) == enable) { return 0; } if (!enable) { destroy_channels(dpif); } else { struct dpif_channel *ch; int error; dpif->epoll_fd = epoll_create(N_CHANNELS); // 用户层和datapath的通信纳入epoll管理,有17个通道; if (dpif->epoll_fd < 0) { return errno; } for (ch = dpif->channels; ch < &dpif->channels[N_CHANNELS]; ch++) { int indx = ch - dpif->channels; struct epoll_event event; error = nl_sock_create(NETLINK_GENERIC, &ch->sock); if (error) { destroy_channels(dpif); return error; } memset(&event, 0, sizeof event); event.events = EPOLLIN; event.data.u32 = indx; if (epoll_ctl(dpif->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(ch->sock), &event) < 0) { error = errno; destroy_channels(dpif); return error; } memset(ch->sketches, 0, sizeof ch->sketches); ch->last_poll = LLONG_MIN; } dpif->ready_mask = 0; dpif->next_scale = time_msec() + SCALE_INTERVAL; } set_upcall_pids(dpif_); return 0; }
OVS中对于用户层和datapath层的多个通道利用epoll进行控制,布布扣,bubuko.com
OVS中对于用户层和datapath层的多个通道利用epoll进行控制
原文:http://blog.csdn.net/vonzhoufz/article/details/38665959