OVS中对于用户层和datapath层的多个通道利用epoll进行控制

来源:互联网 发布:火车票选座位软件 编辑:程序博客网 时间:2024/06/05 10:27

这里先暂时记录下代码流程,有待完善。


static intconstruct(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包。

intdpif_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 intdpif_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;}





0 1