Example #1
0
/**
 *	ovs_vport_add - add vport device (for kernel callers)
 *
 * @parms: Information about new vport.
 *
 * Creates a new vport with the specified configuration (which is dependent on
 * device type).  ovs_mutex must be held.
 *
 * 创建并初始化 vport:
 * 1. 参数校验
 *    * 确保 params->type 在 vport_ops_list(保持所有 vport->ops->type) 中, 返回类型为 params->type 的 ops
 *    * 确保 params->type->ops->owner 的模块是 alive 的
 * 2. 调用 internal_dev_create(params) 创建 vport, 初始化各个数据成员及私有数据
 * 3. 将 vport->hash_node 加入 dev_table
 *
 * 注: 没有初始化的 err_stats, detach_list
 */
struct vport *ovs_vport_add(const struct vport_parms *parms)
{
	struct vport_ops *ops;
	struct vport *vport;

    //确保 params->type 在 vport_ops_list(保持所有 vport->ops->type) 中, 返回
    //类型为 params->type 的 ops
	ops = ovs_vport_lookup(parms);
	if (ops) {
		struct hlist_head *bucket;

        //ops->owner 的模块是 alive 的
		if (!try_module_get(ops->owner))
			return ERR_PTR(-EAFNOSUPPORT);

        //调用 internal_dev_create 创建 vport, 初始化各个数据成员及私有数据
		vport = ops->create(parms);
		if (IS_ERR(vport)) {
            // ops->owener->refcnt = ops->owener->refcnt - 1
			module_put(ops->owner);
			return vport;
		}

		bucket = hash_bucket(ovs_dp_get_net(vport->dp),
				     vport->ops->get_name(vport));
		hlist_add_head_rcu(&vport->hash_node, bucket);
		return vport;
	}

	/* Unlock to attempt module load and return -EAGAIN if load
	 * was successful as we need to restart the port addition
	 * workflow.
	 */
	ovs_unlock();
	request_module("vport-type-%d", parms->type);
	ovs_lock();

	if (!ovs_vport_lookup(parms))
		return ERR_PTR(-EAFNOSUPPORT);
	else
		return ERR_PTR(-EAGAIN);
}
Example #2
0
/**
 *	ovs_vport_add - add vport device (for kernel callers)
 *
 * @parms: Information about new vport.
 *
 * Creates a new vport with the specified configuration (which is dependent on
 * device type).  ovs_mutex must be held.
 */
struct vport *ovs_vport_add(const struct vport_parms *parms)
{
	struct vport_ops *ops;
	struct vport *vport;

	ops = ovs_vport_lookup(parms);
	if (ops) {
		struct hlist_head *bucket;

		if (!try_module_get(ops->owner))
			return ERR_PTR(-EAFNOSUPPORT);

		vport = ops->create(parms);
		if (IS_ERR(vport)) {
			module_put(ops->owner);
			return vport;
		}

		bucket = hash_bucket(ovs_dp_get_net(vport->dp),
				     ovs_vport_name(vport));
		hlist_add_head_rcu(&vport->hash_node, bucket);
		return vport;
	}

	if (parms->type == OVS_VPORT_TYPE_GRE && !compat_gre_loaded) {
		pr_warn("GRE protocol already loaded!\n");
		return ERR_PTR(-EAFNOSUPPORT);
	}
	/* Unlock to attempt module load and return -EAGAIN if load
	 * was successful as we need to restart the port addition
	 * workflow.
	 */
	ovs_unlock();
	request_module("vport-type-%d", parms->type);
	ovs_lock();

	if (!ovs_vport_lookup(parms))
		return ERR_PTR(-EAFNOSUPPORT);
	else
		return ERR_PTR(-EAGAIN);
}