datapath: Move vport init to first port create.
authorPravin B Shelar <pshelar@nicira.com>
Mon, 6 May 2013 17:32:12 +0000 (10:32 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Mon, 6 May 2013 18:42:48 +0000 (11:42 -0700)
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 <pshelar@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
datapath/vport-gre.c
datapath/vport-internal_dev.c
datapath/vport-netdev.c
datapath/vport.c
datapath/vport.h

index 53c6b29..1f046ae 100644 (file)
@@ -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,
index 1e8c304..1b19bfc 100644 (file)
@@ -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,
index 55592f9..9233f90 100644 (file)
@@ -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,
index c2460c5..6f2b2f6 100644 (file)
@@ -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;
 
index 8325ee1..e4b45d8 100644 (file)
@@ -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 *);