From: Jesse Gross <jesse@nicira.com>
Date: Fri, 25 Jan 2013 22:17:49 +0000 (-0800)
Subject: datapath: Remove kernel patch ports.
X-Git-Tag: sliver-openvswitch-1.9.90-3~3^2~12
X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=f18a39b73a3548dd646f274f7555e07926c74371;p=sliver-openvswitch.git

datapath: Remove kernel patch ports.

Now that userspace implements patch ports completely internally,
it's possible to remove the kernel implementation of them.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Kyle Mestery <kmestery@cisco.com>
---

diff --git a/datapath/Modules.mk b/datapath/Modules.mk
index 281408b45..54c6f1378 100644
--- a/datapath/Modules.mk
+++ b/datapath/Modules.mk
@@ -20,7 +20,6 @@ openvswitch_sources = \
 	vport-gre.c \
 	vport-internal_dev.c \
 	vport-netdev.c \
-	vport-patch.c \
 	vport-vxlan.c
 
 openvswitch_headers = \
diff --git a/datapath/vport-patch.c b/datapath/vport-patch.c
deleted file mode 100644
index ca3a18424..000000000
--- a/datapath/vport-patch.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (c) 2007-2012 Nicira, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#include <linux/kernel.h>
-#include <linux/jhash.h>
-#include <linux/list.h>
-#include <linux/rtnetlink.h>
-#include <net/net_namespace.h>
-
-#include "compat.h"
-#include "datapath.h"
-#include "vport.h"
-
-struct patch_config {
-	struct rcu_head rcu;
-
-	char peer_name[IFNAMSIZ];
-};
-
-struct patch_vport {
-	struct rcu_head rcu;
-
-	char name[IFNAMSIZ];
-
-	/* Protected by RTNL lock. */
-	struct hlist_node hash_node;
-
-	struct vport __rcu *peer;
-	struct patch_config __rcu *patchconf;
-};
-
-/* Protected by RTNL lock. */
-static struct hlist_head *peer_table;
-#define PEER_HASH_BUCKETS 256
-
-static void update_peers(struct net *, const char *name, struct vport *);
-
-static struct patch_vport *patch_vport_priv(const struct vport *vport)
-{
-	return vport_priv(vport);
-}
-
-/* RCU callback. */
-static void free_config(struct rcu_head *rcu)
-{
-	struct patch_config *c = container_of(rcu, struct patch_config, rcu);
-	kfree(c);
-}
-
-static void assign_config_rcu(struct vport *vport,
-			      struct patch_config *new_config)
-{
-	struct patch_vport *patch_vport = patch_vport_priv(vport);
-	struct patch_config *old_config;
-
-	old_config = rtnl_dereference(patch_vport->patchconf);
-	rcu_assign_pointer(patch_vport->patchconf, new_config);
-	call_rcu(&old_config->rcu, free_config);
-}
-
-static struct hlist_head *hash_bucket(struct net *net, const char *name)
-{
-	unsigned int hash = jhash(name, strlen(name), (unsigned long) net);
-	return &peer_table[hash & (PEER_HASH_BUCKETS - 1)];
-}
-
-static int patch_init(void)
-{
-	peer_table = kzalloc(PEER_HASH_BUCKETS * sizeof(struct hlist_head),
-			    GFP_KERNEL);
-	if (!peer_table)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static void patch_exit(void)
-{
-	kfree(peer_table);
-}
-
-static const struct nla_policy patch_policy[OVS_PATCH_ATTR_MAX + 1] = {
-#ifdef HAVE_NLA_NUL_STRING
-	[OVS_PATCH_ATTR_PEER] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
-#endif
-};
-
-static int patch_set_config(struct vport *vport, const struct nlattr *options,
-			    struct patch_config *patchconf)
-{
-	struct patch_vport *patch_vport = patch_vport_priv(vport);
-	struct nlattr *a[OVS_PATCH_ATTR_MAX + 1];
-	const char *peer_name;
-	int err;
-
-	if (!options)
-		return -EINVAL;
-
-	err = nla_parse_nested(a, OVS_PATCH_ATTR_MAX, options, patch_policy);
-	if (err)
-		return err;
-
-	if (!a[OVS_PATCH_ATTR_PEER] ||
-	    CHECK_NUL_STRING(a[OVS_PATCH_ATTR_PEER], IFNAMSIZ - 1))
-		return -EINVAL;
-
-	peer_name = nla_data(a[OVS_PATCH_ATTR_PEER]);
-	if (!strcmp(patch_vport->name, peer_name))
-		return -EINVAL;
-
-	strcpy(patchconf->peer_name, peer_name);
-
-	return 0;
-}
-
-static struct vport *patch_create(const struct vport_parms *parms)
-{
-	struct vport *vport;
-	struct patch_vport *patch_vport;
-	const char *peer_name;
-	struct patch_config *patchconf;
-	struct net *net = ovs_dp_get_net(parms->dp);
-	int err;
-
-	vport = ovs_vport_alloc(sizeof(struct patch_vport),
-				&ovs_patch_vport_ops, parms);
-	if (IS_ERR(vport)) {
-		err = PTR_ERR(vport);
-		goto error;
-	}
-
-	patch_vport = patch_vport_priv(vport);
-
-	strcpy(patch_vport->name, parms->name);
-
-	patchconf = kmalloc(sizeof(struct patch_config), GFP_KERNEL);
-	if (!patchconf) {
-		err = -ENOMEM;
-		goto error_free_vport;
-	}
-
-	err = patch_set_config(vport, parms->options, patchconf);
-	if (err)
-		goto error_free_patchconf;
-
-	rcu_assign_pointer(patch_vport->patchconf, patchconf);
-
-	peer_name = patchconf->peer_name;
-	hlist_add_head(&patch_vport->hash_node, hash_bucket(net, peer_name));
-	rcu_assign_pointer(patch_vport->peer, ovs_vport_locate(net, peer_name));
-	update_peers(net, patch_vport->name, vport);
-
-	return vport;
-
-error_free_patchconf:
-	kfree(patchconf);
-error_free_vport:
-	ovs_vport_free(vport);
-error:
-	return ERR_PTR(err);
-}
-
-static void free_port_rcu(struct rcu_head *rcu)
-{
-	struct patch_vport *patch_vport = container_of(rcu,
-					  struct patch_vport, rcu);
-
-	kfree((struct patch_config __force *)patch_vport->patchconf);
-	ovs_vport_free(vport_from_priv(patch_vport));
-}
-
-static void patch_destroy(struct vport *vport)
-{
-	struct patch_vport *patch_vport = patch_vport_priv(vport);
-
-	update_peers(ovs_dp_get_net(vport->dp), patch_vport->name, NULL);
-	hlist_del(&patch_vport->hash_node);
-	call_rcu(&patch_vport->rcu, free_port_rcu);
-}
-
-static int patch_set_options(struct vport *vport, struct nlattr *options)
-{
-	struct patch_vport *patch_vport = patch_vport_priv(vport);
-	struct patch_config *patchconf;
-	int err;
-
-	patchconf = kmemdup(rtnl_dereference(patch_vport->patchconf),
-			  sizeof(struct patch_config), GFP_KERNEL);
-	if (!patchconf) {
-		err = -ENOMEM;
-		goto error;
-	}
-
-	err = patch_set_config(vport, options, patchconf);
-	if (err)
-		goto error_free;
-
-	assign_config_rcu(vport, patchconf);
-
-	hlist_del(&patch_vport->hash_node);
-
-	rcu_assign_pointer(patch_vport->peer,
-		ovs_vport_locate(ovs_dp_get_net(vport->dp), patchconf->peer_name));
-
-	hlist_add_head(&patch_vport->hash_node,
-		       hash_bucket(ovs_dp_get_net(vport->dp), patchconf->peer_name));
-
-	return 0;
-error_free:
-	kfree(patchconf);
-error:
-	return err;
-}
-
-static void update_peers(struct net *net, const char *name, struct vport *vport)
-{
-	struct hlist_head *bucket = hash_bucket(net, name);
-	struct patch_vport *peer_vport;
-	struct hlist_node *node;
-
-	hlist_for_each_entry(peer_vport, node, bucket, hash_node) {
-		struct vport *curr_vport = vport_from_priv(peer_vport);
-		const char *peer_name;
-
-		peer_name = rtnl_dereference(peer_vport->patchconf)->peer_name;
-		if (!strcmp(peer_name, name) && net_eq(ovs_dp_get_net(curr_vport->dp), net))
-			rcu_assign_pointer(peer_vport->peer, vport);
-	}
-}
-
-static const char *patch_get_name(const struct vport *vport)
-{
-	const struct patch_vport *patch_vport = patch_vport_priv(vport);
-	return patch_vport->name;
-}
-
-static int patch_get_options(const struct vport *vport, struct sk_buff *skb)
-{
-	struct patch_vport *patch_vport = patch_vport_priv(vport);
-	struct patch_config *patchconf = rcu_dereference_rtnl(patch_vport->patchconf);
-
-	return nla_put_string(skb, OVS_PATCH_ATTR_PEER, patchconf->peer_name);
-}
-
-static int patch_send(struct vport *vport, struct sk_buff *skb)
-{
-	struct patch_vport *patch_vport = patch_vport_priv(vport);
-	struct vport *peer = rcu_dereference(patch_vport->peer);
-	int skb_len = skb->len;
-
-	if (!peer) {
-		kfree_skb(skb);
-		ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
-
-		return 0;
-	}
-
-	ovs_vport_receive(peer, skb);
-	return skb_len;
-}
-
-const struct vport_ops ovs_patch_vport_ops = {
-	.type		= OVS_VPORT_TYPE_PATCH,
-	.init		= patch_init,
-	.exit		= patch_exit,
-	.create		= patch_create,
-	.destroy	= patch_destroy,
-	.get_name	= patch_get_name,
-	.get_options	= patch_get_options,
-	.set_options	= patch_set_options,
-	.send		= patch_send,
-};
diff --git a/datapath/vport.c b/datapath/vport.c
index eb87c991f..9c0942b4b 100644
--- a/datapath/vport.c
+++ b/datapath/vport.c
@@ -39,7 +39,6 @@
 static const struct vport_ops *base_vport_ops_list[] = {
 	&ovs_netdev_vport_ops,
 	&ovs_internal_vport_ops,
-	&ovs_patch_vport_ops,
 	&ovs_gre_vport_ops,
 	&ovs_gre64_vport_ops,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
diff --git a/datapath/vport.h b/datapath/vport.h
index e4de41d6f..ed089a958 100644
--- a/datapath/vport.h
+++ b/datapath/vport.h
@@ -228,7 +228,6 @@ void ovs_vport_record_error(struct vport *, enum vport_err_type err_type);
  * add yours to the list at the top of vport.c. */
 extern const struct vport_ops ovs_netdev_vport_ops;
 extern const struct vport_ops ovs_internal_vport_ops;
-extern const struct vport_ops ovs_patch_vport_ops;
 extern const struct vport_ops ovs_gre_vport_ops;
 extern const struct vport_ops ovs_gre64_vport_ops;
 extern const struct vport_ops ovs_capwap_vport_ops;
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index 5ad0bc00c..b12bf0c83 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -184,7 +184,6 @@ enum ovs_vport_type {
 	OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */
 	OVS_VPORT_TYPE_GRE,	 /* GRE tunnel. */
 	OVS_VPORT_TYPE_VXLAN,    /* VXLAN tunnel */
-	OVS_VPORT_TYPE_PATCH = 100, /* virtual tunnel connecting two vports */
 	OVS_VPORT_TYPE_CAPWAP = 102,  /* CAPWAP tunnel */
 	OVS_VPORT_TYPE_GRE64 = 104, /* GRE tunnel with 64-bit keys */
 	__OVS_VPORT_TYPE_MAX
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 98ef18669..94f1110c2 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -78,6 +78,7 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
 
 static int netdev_vport_create(const struct netdev_class *, const char *,
                                struct netdev_dev **);
+static int get_patch_config(struct netdev_dev *, struct smap *args);
 static void netdev_vport_poll_notify(const struct netdev *);
 static int tnl_port_config_from_nlattr(const struct nlattr *options,
                                        size_t options_len,
@@ -144,7 +145,10 @@ netdev_vport_get_vport_type(const struct netdev *netdev)
 bool
 netdev_vport_is_patch(const struct netdev *netdev)
 {
-    return netdev_vport_get_vport_type(netdev) == OVS_VPORT_TYPE_PATCH;
+    const struct netdev_dev *dev = netdev_get_dev(netdev);
+    const struct netdev_class *class = netdev_dev_get_class(dev);
+
+    return class->get_config == get_patch_config; 
 }
 
 static uint32_t
@@ -168,9 +172,6 @@ netdev_vport_get_netdev_type(const struct dpif_linux_vport *vport)
     case OVS_VPORT_TYPE_INTERNAL:
         return "internal";
 
-    case OVS_VPORT_TYPE_PATCH:
-        return "patch";
-
     case OVS_VPORT_TYPE_GRE:
         if (tnl_port_config_from_nlattr(vport->options, vport->options_len,
                                         a)) {
@@ -915,7 +916,7 @@ netdev_vport_register(void)
         TUNNEL_CLASS("capwap", OVS_VPORT_TYPE_CAPWAP),
         TUNNEL_CLASS("vxlan", OVS_VPORT_TYPE_VXLAN),
 
-        { OVS_VPORT_TYPE_PATCH,
+        { OVS_VPORT_TYPE_UNSPEC,
           { "patch", VPORT_FUNCTIONS(get_patch_config,
                                      set_patch_config,
                                      NULL,