这里先暂时记录下代码流程,有待完善。
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;
}
具体是dpif_linux_class的实现:
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;
}