【OVS2.5.0源码分析】openflow连接实现分析(4)
来源:互联网 发布:微信推广淘宝商品 编辑:程序博客网 时间:2024/06/05 03:48
前面几篇介绍controller的连接,这篇分析ofservice的创建过程,直接从bridge_configure_remotes函数开始分析。
1、bridge_configure_remotes函数
n_controllers = bridge_get_controllers(br, &controllers); ocs = xmalloc((n_controllers + 1) * sizeof *ocs); n_ocs = 0; bridge_ofproto_controller_for_mgmt(br, &ocs[n_ocs++]); //如果没有配置controller,那么也存在一个controller,punix的连接方式 for (i = 0; i < n_controllers; i++) { struct ovsrec_controller *c = controllers[i]; if (!strncmp(c->target, "punix:", 6) || !strncmp(c->target, "unix:", 5)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); char *whitelist; if (!strncmp(c->target, "unix:", 5)) { /* Connect to a listening socket */ whitelist = xasprintf("unix:%s/", ovs_rundir()); if (strchr(c->target, '/') && !equal_pathnames(c->target, whitelist, strlen(whitelist))) { /* Absolute path specified, but not in ovs_rundir */ VLOG_ERR_RL(&rl, "bridge %s: Not connecting to socket " "controller \"%s\" due to possibility for " "remote exploit. Instead, specify socket " "in whitelisted \"%s\" or connect to " "\"unix:%s/%s.mgmt\" (which is always " "available without special configuration).", br->name, c->target, whitelist, ovs_rundir(), br->name); free(whitelist); continue; } } else { whitelist = xasprintf("punix:%s/%s.", ovs_rundir(), br->name); if (!equal_pathnames(c->target, whitelist, strlen(whitelist)) || strchr(c->target + strlen(whitelist), '/')) { /* Prevent remote ovsdb-server users from accessing * arbitrary Unix domain sockets and overwriting arbitrary * local files. */ VLOG_ERR_RL(&rl, "bridge %s: Not adding Unix domain socket " "controller \"%s\" due to possibility of " "overwriting local files. Instead, specify " "path in whitelisted format \"%s*\" or " "connect to \"unix:%s/%s.mgmt\" (which is " "always available without special " "configuration).", br->name, c->target, whitelist, ovs_rundir(), br->name); free(whitelist); continue; } } free(whitelist); } bridge_configure_local_iface_netdev(br, c); bridge_ofproto_controller_from_ovsrec(c, &ocs[n_ocs]); if (disable_in_band) { ocs[n_ocs].band = OFPROTO_OUT_OF_BAND; } n_ocs++; } ofproto_set_controllers(br->ofproto, ocs, n_ocs, //controller和service统一接口 bridge_get_allowed_versions(br)); free(ocs[0].target); /* From bridge_ofproto_controller_for_mgmt(). */ free(ocs);
voidofproto_set_controllers(struct ofproto *p, const struct ofproto_controller *controllers, size_t n_controllers, uint32_t allowed_versions){ connmgr_set_controllers(p->connmgr, controllers, n_controllers, allowed_versions);}
3、connmgr_set_controllers函数
voidconnmgr_set_controllers(struct connmgr *mgr, const struct ofproto_controller *controllers, size_t n_controllers, uint32_t allowed_versions) OVS_EXCLUDED(ofproto_mutex){ bool had_controllers = connmgr_has_controllers(mgr); struct shash new_controllers; struct ofconn *ofconn, *next_ofconn; struct ofservice *ofservice, *next_ofservice; size_t i; /* Required to add and remove ofconns. This could probably be narrowed to * cover a smaller amount of code, if that yielded some benefit. */ ovs_mutex_lock(&ofproto_mutex); /* Create newly configured controllers and services. * Create a name to ofproto_controller mapping in 'new_controllers'. */ shash_init(&new_controllers); for (i = 0; i < n_controllers; i++) { const struct ofproto_controller *c = &controllers[i]; if (!vconn_verify_name(c->target)) { bool add = false; ofconn = find_controller_by_target(mgr, c->target); if (!ofconn) { VLOG_INFO("%s: added primary controller \"%s\"", mgr->name, c->target); add = true; } else if (rconn_get_allowed_versions(ofconn->rconn) != allowed_versions) { VLOG_INFO("%s: re-added primary controller \"%s\"", mgr->name, c->target); add = true; ofconn_destroy(ofconn); } if (add) { add_controller(mgr, c->target, c->dscp, allowed_versions); } } else if (!pvconn_verify_name(c->target)) { bool add = false; ofservice = ofservice_lookup(mgr, c->target); if (!ofservice) { VLOG_INFO("%s: added service controller \"%s\"", mgr->name, c->target); add = true; } else if (ofservice->allowed_versions != allowed_versions) { VLOG_INFO("%s: re-added service controller \"%s\"", mgr->name, c->target); ofservice_destroy(mgr, ofservice); add = true; } if (add) { ofservice_create(mgr, c->target, allowed_versions, c->dscp); //创建ofservice } } else { VLOG_WARN_RL(&rl, "%s: unsupported controller \"%s\"", mgr->name, c->target); continue; } shash_add_once(&new_controllers, c->target, &controllers[i]); }
4、ofservice_create函数
static intofservice_create(struct connmgr *mgr, const char *target, uint32_t allowed_versions, uint8_t dscp){ struct ofservice *ofservice; struct pvconn *pvconn; int error; error = pvconn_open(target, allowed_versions, dscp, &pvconn); //创建pvconn if (error) { return error; } ofservice = xzalloc(sizeof *ofservice); hmap_insert(&mgr->services, &ofservice->node, hash_string(target, 0));//添加到服务清单,在connmgr_run函数中会使用到 ofservice->pvconn = pvconn; ofservice->allowed_versions = allowed_versions; return 0;}
5、pvconn_open函数
intpvconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp, struct pvconn **pvconnp){ const struct pvconn_class *class; struct pvconn *pvconn; char *suffix_copy; int error; check_vconn_classes(); if (!allowed_versions) { allowed_versions = OFPUTIL_DEFAULT_VERSIONS; } /* Look up the class. */ error = pvconn_lookup_class(name, &class); if (!class) { goto error; } /* Call class's "open" function. */ suffix_copy = xstrdup(strchr(name, ':') + 1); error = class->listen(name, allowed_versions, suffix_copy, &pvconn, dscp); //实际调用pvconn_pstream_listen函数 free(suffix_copy); if (error) { goto error; } /* Success. */ *pvconnp = pvconn; return 0;error: *pvconnp = NULL; return error;}
6、pvconn_pstream_listen函数
static intpvconn_pstream_listen(const char *name, uint32_t allowed_versions, char *suffix OVS_UNUSED, struct pvconn **pvconnp, uint8_t dscp){ struct pvconn_pstream *ps; struct pstream *pstream; int error; error = pstream_open_with_default_port(name, OFP_PORT, &pstream, dscp); //创建pstream if (error) { return error; } ps = xmalloc(sizeof *ps); pvconn_init(&ps->pvconn, &pstream_pvconn_class, name, allowed_versions); ps->pstream = pstream; *pvconnp = &ps->pvconn; return 0;}
7、pstream_open_with_default_port函数
intpstream_open_with_default_port(const char *name_, uint16_t default_port, struct pstream **pstreamp, uint8_t dscp){ char *name; int error; if ((!strncmp(name_, "ptcp:", 5) || !strncmp(name_, "pssl:", 5)) && count_fields(name_) < 2) { name = xasprintf("%s%d", name_, default_port); } else { name = xstrdup(name_); } error = pstream_open(name, pstreamp, dscp); free(name); return error;}
8、pstream_open函数
intpstream_open(const char *name, struct pstream **pstreamp, uint8_t dscp){ const struct pstream_class *class; struct pstream *pstream; char *suffix_copy; int error; COVERAGE_INC(pstream_open); /* Look up the class. */ error = pstream_lookup_class(name, &class); //punix类型的class为punix_pstream_class if (!class) { goto error; } /* Call class's "open" function. */ suffix_copy = xstrdup(strchr(name, ':') + 1); error = class->listen(name, suffix_copy, &pstream, dscp); //<span style="font-family: Arial, Helvetica, sans-serif;">punix类型的listen函数为punix_open</span> free(suffix_copy); if (error) { goto error; } /* Success. */ *pstreamp = pstream; return 0;error: *pstreamp = NULL; return error;}
9、punix_open函数
static intpunix_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp, uint8_t dscp OVS_UNUSED){ char *bind_path; int fd, error; bind_path = abs_file_name(ovs_rundir(), suffix); fd = make_unix_socket(SOCK_STREAM, true, bind_path, NULL); //创建unix socket if (fd < 0) { VLOG_ERR("%s: binding failed: %s", bind_path, ovs_strerror(errno)); free(bind_path); return errno; } if (listen(fd, 64) < 0) { error = errno; VLOG_ERR("%s: listen: %s", name, ovs_strerror(error)); close(fd); free(bind_path); return error; } return new_fd_pstream(name, fd, punix_accept, bind_path, pstreamp); //创建pstream对象,pstream_class为fd_pstream_class}
10、make_unix_socket函数
intmake_unix_socket(int style, bool nonblock, const char *bind_path, const char *connect_path){ int error; int fd; fd = socket(PF_UNIX, style, 0); if (fd < 0) { return -errno; } /* Set nonblocking mode right away, if we want it. This prevents blocking * in connect(), if connect_path != NULL. (In turn, that's a corner case: * it will only happen if style is SOCK_STREAM or SOCK_SEQPACKET, and only * if a backlog of un-accepted connections has built up in the kernel.) */ if (nonblock) { error = set_nonblocking(fd); if (error) { goto error; } } if (bind_path) { //pstream进这个分支 char linkname[MAX_UN_LEN + 1]; struct sockaddr_un un; socklen_t un_len; int dirfd; if (unlink(bind_path) && errno != ENOENT) { VLOG_WARN("unlinking \"%s\": %s\n", bind_path, ovs_strerror(errno)); } fatal_signal_add_file_to_unlink(bind_path); error = make_sockaddr_un(bind_path, &un, &un_len, &dirfd, linkname); if (!error) { error = bind_unix_socket(fd, (struct sockaddr *) &un, un_len); } free_sockaddr_un(dirfd, linkname); if (error) { goto error; } } if (connect_path) { //stream进这个分支 char linkname[MAX_UN_LEN + 1]; struct sockaddr_un un; socklen_t un_len; int dirfd; error = make_sockaddr_un(connect_path, &un, &un_len, &dirfd, linkname); if (!error && connect(fd, (struct sockaddr*) &un, un_len) && errno != EINPROGRESS) { error = errno; } free_sockaddr_un(dirfd, linkname); if (error) { goto error; } } return fd;error: if (error == EAGAIN) { error = EPROTO; } if (bind_path) { fatal_signal_unlink_file_now(bind_path); } close(fd); return -error;}
ofservice最终也是linux socket,调用关系和ofconn非常类似,只是一个最终是pstream(作为server角色),而另一个最终是stream(作为client角色)。 ofservice的类结果关系如下图:
0 0
- 【OVS2.5.0源码分析】openflow连接实现分析(4)
- 【OVS2.5.0源码分析】openflow连接实现分析(1)
- 【OVS2.5.0源码分析】openflow连接实现分析(2)
- 【OVS2.5.0源码分析】openflow连接实现分析(3)
- 【OVS2.5.0源码分析】openflow连接实现分析(5)
- 【OVS2.5.0源码分析】openflow连接实现分析(6)
- 【OVS2.5.0源码分析】sFlow实现分析(1)
- 【OVS2.5.0源码分析】sFlow实现分析(2)
- 【OVS2.5.0源码分析】sFlow实现分析(3)
- 【OVS2.5.0源码分析】datapath之action分析(4)
- 【OVS2.5.0源码分析】upcall处理线程分析(4)
- 【OVS2.5.0源码分析】mirror实现原理(1)
- 【OVS2.5.0源码分析】mirror实现原理(2)
- 【OVS2.5.0源码分析】bridge&bundle&port分析(1)
- 【OVS2.5.0源码分析】ovsd进程运行机制分析(1)
- 【OVS2.5.0源码分析】datapath之action分析(1)
- 【OVS2.5.0源码分析】upcall处理线程分析(1)
- 【OVS2.5.0源码分析】datapath之action分析(2)
- wordprss只显示一个当前主题 问题的解决
- 剑指Offer_57_二叉树的下一个结点
- 装饰模式(Decorator Pattern)
- RFS keyword 8/27
- CSS样式中,background-image 背景图片如何居中显示
- 【OVS2.5.0源码分析】openflow连接实现分析(4)
- 应届生面试嵌入式工程师的一点点经验
- jQuery的deferred
- lombok使用
- think python turtleworld练习
- Mybatis 3+Mysql 实现批量插入
- 设计模式之禅——代理模式(二)代理模式&AOP编程&JDK对代理模式的支持
- 三大运营商号段分配
- 简单排序--冒泡排序