From 806b46ef3d1f3e17e87d91c4fb0041aa87709497 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 6 May 2013 10:32:12 -0700 Subject: [PATCH] datapath: Move vport init to first port create. vport->init and exit() functions are defined by gre and netdev vport only and both can be moved to first port create. Following patch does same, it moves vport init to respective vport create and gets rid of vport->init() and vport->exit() functions. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross --- datapath/vport-gre.c | 51 ++++++++++++++++++++---------- datapath/vport-internal_dev.c | 1 - datapath/vport-netdev.c | 19 +++++++++--- datapath/vport.c | 58 ++++------------------------------- datapath/vport.h | 11 +------ 5 files changed, 55 insertions(+), 85 deletions(-) diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c index 53c6b29d1..1f046aea8 100644 --- a/datapath/vport-gre.c +++ b/datapath/vport-gre.c @@ -290,16 +290,15 @@ static const struct net_protocol gre_protocol_handlers = { #endif }; -static bool inited; - +static int gre_ports; static int gre_init(void) { int err; - if (inited) + gre_ports++; + if (gre_ports > 1) return 0; - inited = true; err = inet_add_protocol(&gre_protocol_handlers, IPPROTO_GRE); if (err) pr_warn("cannot register gre protocol handler\n"); @@ -309,11 +308,10 @@ static int gre_init(void) static void gre_exit(void) { - if (!inited) + gre_ports--; + if (gre_ports > 0) return; - inited = false; - inet_del_protocol(&gre_protocol_handlers, IPPROTO_GRE); } @@ -327,18 +325,29 @@ static struct vport *gre_create(const struct vport_parms *parms) struct net *net = ovs_dp_get_net(parms->dp); struct ovs_net *ovs_net; struct vport *vport; + int err; + + err = gre_init(); + if (err) + return ERR_PTR(err); ovs_net = net_generic(net, ovs_net_id); - if (ovsl_dereference(ovs_net->vport_net.gre_vport)) - return ERR_PTR(-EEXIST); + if (ovsl_dereference(ovs_net->vport_net.gre_vport)) { + vport = ERR_PTR(-EEXIST); + goto error; + } vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre_vport_ops, parms); if (IS_ERR(vport)) - return vport; + goto error; strncpy(vport_priv(vport), parms->name, IFNAMSIZ); rcu_assign_pointer(ovs_net->vport_net.gre_vport, vport); return vport; + +error: + gre_exit(); + return vport; } static void gre_tnl_destroy(struct vport *vport) @@ -350,6 +359,7 @@ static void gre_tnl_destroy(struct vport *vport) rcu_assign_pointer(ovs_net->vport_net.gre_vport, NULL); ovs_vport_deferred_free(vport); + gre_exit(); } static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) @@ -366,8 +376,6 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) const struct vport_ops ovs_gre_vport_ops = { .type = OVS_VPORT_TYPE_GRE, .flags = VPORT_F_TUN_ID, - .init = gre_init, - .exit = gre_exit, .create = gre_create, .destroy = gre_tnl_destroy, .get_name = gre_get_name, @@ -380,18 +388,28 @@ static struct vport *gre64_create(const struct vport_parms *parms) struct net *net = ovs_dp_get_net(parms->dp); struct ovs_net *ovs_net; struct vport *vport; + int err; + + err = gre_init(); + if (err) + return ERR_PTR(err); ovs_net = net_generic(net, ovs_net_id); - if (ovsl_dereference(ovs_net->vport_net.gre64_vport)) - return ERR_PTR(-EEXIST); + if (ovsl_dereference(ovs_net->vport_net.gre64_vport)) { + vport = ERR_PTR(-EEXIST); + goto error; + } vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre64_vport_ops, parms); if (IS_ERR(vport)) - return vport; + goto error; strncpy(vport_priv(vport), parms->name, IFNAMSIZ); rcu_assign_pointer(ovs_net->vport_net.gre64_vport, vport); return vport; +error: + gre_exit(); + return vport; } static void gre64_tnl_destroy(struct vport *vport) @@ -403,6 +421,7 @@ static void gre64_tnl_destroy(struct vport *vport) rcu_assign_pointer(ovs_net->vport_net.gre64_vport, NULL); ovs_vport_deferred_free(vport); + gre_exit(); } static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb) @@ -419,8 +438,6 @@ static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb) const struct vport_ops ovs_gre64_vport_ops = { .type = OVS_VPORT_TYPE_GRE64, .flags = VPORT_F_TUN_ID, - .init = gre_init, - .exit = gre_exit, .create = gre64_create, .destroy = gre64_tnl_destroy, .get_name = gre_get_name, diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c index 1e8c3043c..1b19bfc72 100644 --- a/datapath/vport-internal_dev.c +++ b/datapath/vport-internal_dev.c @@ -294,7 +294,6 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb) const struct vport_ops ovs_internal_vport_ops = { .type = OVS_VPORT_TYPE_INTERNAL, - .flags = VPORT_F_REQUIRED, .create = internal_dev_create, .destroy = internal_dev_destroy, .get_name = ovs_netdev_get_name, diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c index 55592f988..9233f9053 100644 --- a/datapath/vport-netdev.c +++ b/datapath/vport-netdev.c @@ -117,17 +117,27 @@ static int netdev_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb) static int netdev_init(void) { return 0; } static void netdev_exit(void) { } #else -static int netdev_init(void) +static int port_count; + +static void netdev_init(void) { + port_count++; + if (port_count > 1) + return; + /* Hook into callback used by the bridge to intercept packets. * Parasites we are. */ br_handle_frame_hook = netdev_frame_hook; - return 0; + return; } static void netdev_exit(void) { + port_count--; + if (port_count > 0) + return; + br_handle_frame_hook = NULL; } #endif @@ -179,6 +189,7 @@ static struct vport *netdev_create(const struct vport_parms *parms) netdev_vport->dev->priv_flags |= IFF_OVS_DATAPATH; rtnl_unlock(); + netdev_init(); return vport; #ifndef HAVE_RHEL_OVS_HOOK @@ -212,6 +223,7 @@ static void netdev_destroy(struct vport *vport) { struct netdev_vport *netdev_vport = netdev_vport_priv(vport); + netdev_exit(); rtnl_lock(); netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH; netdev_rx_handler_unregister(netdev_vport->dev); @@ -383,9 +395,6 @@ struct vport *ovs_netdev_get_vport(struct net_device *dev) const struct vport_ops ovs_netdev_vport_ops = { .type = OVS_VPORT_TYPE_NETDEV, - .flags = VPORT_F_REQUIRED, - .init = netdev_init, - .exit = netdev_exit, .create = netdev_create, .destroy = netdev_destroy, .get_name = ovs_netdev_get_name, diff --git a/datapath/vport.c b/datapath/vport.c index c2460c508..6f2b2f640 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -36,7 +36,7 @@ /* List of statically compiled vport implementations. Don't forget to also * add yours to the list at the bottom of vport.h. */ -static const struct vport_ops *base_vport_ops_list[] = { +static const struct vport_ops *vport_ops_list[] = { &ovs_netdev_vport_ops, &ovs_internal_vport_ops, &ovs_gre_vport_ops, @@ -47,9 +47,6 @@ static const struct vport_ops *base_vport_ops_list[] = { #endif }; -static const struct vport_ops **vport_ops_list; -static int n_vport_types; - /* Protected by RCU read lock for reading, ovs_mutex for writing. */ static struct hlist_head *dev_table; #define VPORT_HASH_BUCKETS 1024 @@ -57,68 +54,25 @@ static struct hlist_head *dev_table; /** * ovs_vport_init - initialize vport subsystem * - * Called at module load time to initialize the vport subsystem and any - * compiled in vport types. + * Called at module load time to initialize the vport subsystem. */ int ovs_vport_init(void) { - int err; - int i; - dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head), GFP_KERNEL); - if (!dev_table) { - err = -ENOMEM; - goto error; - } - - vport_ops_list = kmalloc(ARRAY_SIZE(base_vport_ops_list) * - sizeof(struct vport_ops *), GFP_KERNEL); - if (!vport_ops_list) { - err = -ENOMEM; - goto error_dev_table; - } - - for (i = 0; i < ARRAY_SIZE(base_vport_ops_list); i++) { - const struct vport_ops *new_ops = base_vport_ops_list[i]; - - if (new_ops->init) - err = new_ops->init(); - else - err = 0; - - if (!err) - vport_ops_list[n_vport_types++] = new_ops; - else if (new_ops->flags & VPORT_F_REQUIRED) { - ovs_vport_exit(); - goto error; - } - } + if (!dev_table) + return -ENOMEM; return 0; - -error_dev_table: - kfree(dev_table); -error: - return err; } /** * ovs_vport_exit - shutdown vport subsystem * - * Called at module exit time to shutdown the vport subsystem and any - * initialized vport types. + * Called at module exit time to shutdown the vport subsystem. */ void ovs_vport_exit(void) { - int i; - - for (i = 0; i < n_vport_types; i++) { - if (vport_ops_list[i]->exit) - vport_ops_list[i]->exit(); - } - - kfree(vport_ops_list); kfree(dev_table); } @@ -222,7 +176,7 @@ struct vport *ovs_vport_add(const struct vport_parms *parms) int err = 0; int i; - for (i = 0; i < n_vport_types; i++) { + for (i = 0; i < ARRAY_SIZE(vport_ops_list); i++) { if (vport_ops_list[i]->type == parms->type) { struct hlist_head *bucket; diff --git a/datapath/vport.h b/datapath/vport.h index 8325ee1a7..e4b45d839 100644 --- a/datapath/vport.h +++ b/datapath/vport.h @@ -94,8 +94,7 @@ struct vport { struct ovs_vport_stats offset_stats; }; -#define VPORT_F_REQUIRED (1 << 0) /* If init fails, module loading fails. */ -#define VPORT_F_TUN_ID (1 << 1) /* Sets OVS_CB(skb)->tun_id. */ +#define VPORT_F_TUN_ID (1 << 0) /* Sets OVS_CB(skb)->tun_id. */ /** * struct vport_parms - parameters for creating a new vport @@ -124,10 +123,6 @@ struct vport_parms { * @type: %OVS_VPORT_TYPE_* value for this type of virtual port. * @flags: Flags of type VPORT_F_* that influence how the generic vport layer * handles this vport. - * @init: Called at module initialization. If VPORT_F_REQUIRED is set then the - * failure of this function will cause the module to not load. If the flag is - * not set and initialzation fails then no vports of this type can be created. - * @exit: Called at module unload. * @create: Create a new vport configured as specified. On success returns * a new vport allocated with ovs_vport_alloc(), otherwise an ERR_PTR() value. * @destroy: Destroys a vport. Must call vport_free() on the vport but not @@ -145,10 +140,6 @@ struct vport_ops { enum ovs_vport_type type; u32 flags; - /* Called at module init and exit respectively. */ - int (*init)(void); - void (*exit)(void); - /* Called with ovs_mutex. */ struct vport *(*create)(const struct vport_parms *); void (*destroy)(struct vport *); -- 2.43.0