/** * 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); }
/** * 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); }