[ovs-dev] [kill-dp_port 3/3] datapath: Merge "struct dp_port" into "struct vport".

Ben Pfaff blp at nicira.com
Thu Sep 2 17:57:48 UTC 2010


After the previous commit, which changed the datapath to always create and
attach a vport at the same time, and to always detach and delete a vport
at the same time, there is no longer any real distinction between a dp_port
and a vport.  This commit, therefore, merges the two together to simplify
code.  It might even improve performance, although I have not checked.

I wasn't sure at first whether the merged structure should be "struct
dp_port" or "struct vport".  I went with the latter since the "v" prefix
sounds cool.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 datapath/actions.c            |   14 ++--
 datapath/datapath.c           |  126 +++++++++++++++-------------------------
 datapath/datapath.h           |   37 ++----------
 datapath/dp_notify.c          |   15 ++---
 datapath/dp_sysfs.h           |    6 +-
 datapath/dp_sysfs_dp.c        |   19 ++-----
 datapath/dp_sysfs_if.c        |   54 +++++++++---------
 datapath/vport-internal_dev.c |   15 +----
 datapath/vport-patch.c        |    8 +--
 datapath/vport.c              |  112 ++++++++++++------------------------
 datapath/vport.h              |   24 +++++++-
 11 files changed, 163 insertions(+), 267 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index b75aecd..89f2d09 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -382,7 +382,7 @@ static bool is_spoofed_arp(struct sk_buff *skb, const struct odp_flow_key *key)
 
 static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
 {
-	struct dp_port *p;
+	struct vport *p;
 
 	if (!skb)
 		goto error;
@@ -391,7 +391,7 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
 	if (!p)
 		goto error;
 
-	vport_send(p->vport, skb);
+	vport_send(p, skb);
 	return;
 
 error:
@@ -410,8 +410,8 @@ static int output_group(struct datapath *dp, __u16 group,
 	if (!g)
 		return -1;
 	for (i = 0; i < g->n_ports; i++) {
-		struct dp_port *p = rcu_dereference(dp->ports[g->ports[i]]);
-		if (!p || OVS_CB(skb)->dp_port == p)
+		struct vport *p = rcu_dereference(dp->ports[g->ports[i]]);
+		if (!p || OVS_CB(skb)->vport == p)
 			continue;
 		if (prev_port != -1) {
 			struct sk_buff *clone = skb_clone(skb, gfp);
@@ -437,7 +437,7 @@ static int output_control(struct datapath *dp, struct sk_buff *skb, u32 arg,
  * information about what happened to it. */
 static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
 			 const union odp_action *a, int n_actions,
-			 gfp_t gfp, struct dp_port *dp_port)
+			 gfp_t gfp, struct vport *vport)
 {
 	struct odp_sflow_sample_header *hdr;
 	unsigned int actlen = n_actions * sizeof(union odp_action);
@@ -451,7 +451,7 @@ static void sflow_sample(struct datapath *dp, struct sk_buff *skb,
 	memcpy(__skb_push(nskb, actlen), a, actlen);
 	hdr = (struct odp_sflow_sample_header*)__skb_push(nskb, hdrlen);
 	hdr->n_actions = n_actions;
-	hdr->sample_pool = atomic_read(&dp_port->sflow_pool);
+	hdr->sample_pool = atomic_read(&vport->sflow_pool);
 	dp_output_control(dp, nskb, _ODPL_SFLOW_NR, 0);
 }
 
@@ -470,7 +470,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
 	int err;
 
 	if (dp->sflow_probability) {
-		struct dp_port *p = OVS_CB(skb)->dp_port;
+		struct vport *p = OVS_CB(skb)->vport;
 		if (p) {
 			atomic_inc(&p->sflow_pool);
 			if (dp->sflow_probability == UINT_MAX ||
diff --git a/datapath/datapath.c b/datapath/datapath.c
index f2fd83a..6b7e03e 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -65,7 +65,7 @@ EXPORT_SYMBOL(dp_ioctl_hook);
  * dp_mutex nests inside the RTNL lock: if you need both you must take the RTNL
  * lock first.
  *
- * It is safe to access the datapath and dp_port structures with just
+ * It is safe to access the datapath and vport structures with just
  * dp_mutex.
  */
 static struct datapath *dps[ODP_MAX];
@@ -88,7 +88,7 @@ struct percpu_loop_counters {
 
 static DEFINE_PER_CPU(struct percpu_loop_counters, dp_loop_counters);
 
-static int new_dp_port(struct datapath *, struct odp_port *, int port_no);
+static int new_vport(struct datapath *, struct odp_port *, int port_no);
 
 /* Must be called with rcu_read_lock or dp_mutex. */
 struct datapath *get_dp(int dp_idx)
@@ -114,7 +114,7 @@ static struct datapath *get_dp_locked(int dp_idx)
 /* Must be called with rcu_read_lock or RTNL lock. */
 const char *dp_name(const struct datapath *dp)
 {
-	return vport_get_name(dp->ports[ODPP_LOCAL]->vport);
+	return vport_get_name(dp->ports[ODPP_LOCAL]);
 }
 
 static inline size_t br_nlmsg_size(void)
@@ -129,12 +129,12 @@ static inline size_t br_nlmsg_size(void)
 }
 
 static int dp_fill_ifinfo(struct sk_buff *skb,
-			  const struct dp_port *port,
+			  const struct vport *port,
 			  int event, unsigned int flags)
 {
 	const struct datapath *dp = port->dp;
-	int ifindex = vport_get_ifindex(port->vport);
-	int iflink = vport_get_iflink(port->vport);
+	int ifindex = vport_get_ifindex(port);
+	int iflink = vport_get_iflink(port);
 	struct ifinfomsg *hdr;
 	struct nlmsghdr *nlh;
 
@@ -153,21 +153,20 @@ static int dp_fill_ifinfo(struct sk_buff *skb,
 	hdr->__ifi_pad = 0;
 	hdr->ifi_type = ARPHRD_ETHER;
 	hdr->ifi_index = ifindex;
-	hdr->ifi_flags = vport_get_flags(port->vport);
+	hdr->ifi_flags = vport_get_flags(port);
 	hdr->ifi_change = 0;
 
-	NLA_PUT_STRING(skb, IFLA_IFNAME, vport_get_name(port->vport));
-	NLA_PUT_U32(skb, IFLA_MASTER, vport_get_ifindex(dp->ports[ODPP_LOCAL]->vport));
-	NLA_PUT_U32(skb, IFLA_MTU, vport_get_mtu(port->vport));
+	NLA_PUT_STRING(skb, IFLA_IFNAME, vport_get_name(port));
+	NLA_PUT_U32(skb, IFLA_MASTER, vport_get_ifindex(dp->ports[ODPP_LOCAL]));
+	NLA_PUT_U32(skb, IFLA_MTU, vport_get_mtu(port));
 #ifdef IFLA_OPERSTATE
 	NLA_PUT_U8(skb, IFLA_OPERSTATE,
-		   vport_is_running(port->vport)
-			? vport_get_operstate(port->vport)
+		   vport_is_running(port)
+			? vport_get_operstate(port)
 			: IF_OPER_DOWN);
 #endif
 
-	NLA_PUT(skb, IFLA_ADDRESS, ETH_ALEN,
-					vport_get_addr(port->vport));
+	NLA_PUT(skb, IFLA_ADDRESS, ETH_ALEN, vport_get_addr(port));
 
 	if (ifindex != iflink)
 		NLA_PUT_U32(skb, IFLA_LINK,iflink);
@@ -179,7 +178,7 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
-static void dp_ifinfo_notify(int event, struct dp_port *port)
+static void dp_ifinfo_notify(int event, struct vport *port)
 {
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
@@ -272,7 +271,7 @@ static int create_dp(int dp_idx, const char __user *devnamep)
 	BUILD_BUG_ON(sizeof(internal_dev_port.devname) != sizeof(devname));
 	strcpy(internal_dev_port.devname, devname);
 	strcpy(internal_dev_port.type, "internal");
-	err = new_dp_port(dp, &internal_dev_port, ODPP_LOCAL);
+	err = new_vport(dp, &internal_dev_port, ODPP_LOCAL);
 	if (err) {
 		if (err == -EBUSY)
 			err = -EEXIST;
@@ -310,7 +309,7 @@ err:
 
 static void do_destroy_dp(struct datapath *dp)
 {
-	struct dp_port *p, *n;
+	struct vport *p, *n;
 	int i;
 
 	list_for_each_entry_safe (p, n, &dp->port_list, node)
@@ -355,24 +354,10 @@ err_unlock:
 	return err;
 }
 
-static void release_dp_port(struct kobject *kobj)
-{
-	struct dp_port *p = container_of(kobj, struct dp_port, kobj);
-	kfree(p);
-}
-
-static struct kobj_type brport_ktype = {
-#ifdef CONFIG_SYSFS
-	.sysfs_ops = &brport_sysfs_ops,
-#endif
-	.release = release_dp_port
-};
-
 /* Called with RTNL lock and dp_mutex. */
-static int new_dp_port(struct datapath *dp, struct odp_port *odp_port, int port_no)
+static int new_vport(struct datapath *dp, struct odp_port *odp_port, int port_no)
 {
 	struct vport *vport;
-	struct dp_port *p;
 	int err;
 
 	vport_lock();
@@ -382,31 +367,20 @@ static int new_dp_port(struct datapath *dp, struct odp_port *odp_port, int port_
 	if (IS_ERR(vport))
 		return PTR_ERR(vport);
 
-	p = kzalloc(sizeof(*p), GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-
-	p->port_no = port_no;
-	p->dp = dp;
-	p->vport = vport;
-	atomic_set(&p->sflow_pool, 0);
+	vport->dp = dp;
+	vport->port_no = port_no;
 
-	err = vport_attach(vport, p);
+	err = vport_attach(vport);
 	if (err) {
-		kfree(p);
+		vport_del(vport);
 		return err;
 	}
 
-	rcu_assign_pointer(dp->ports[port_no], p);
-	list_add_rcu(&p->node, &dp->port_list);
+	rcu_assign_pointer(dp->ports[port_no], vport);
+	list_add_rcu(&vport->node, &dp->port_list);
 	dp->n_ports++;
 
-	/* Initialize kobject for bridge.  This will be added as
-	 * /sys/class/net/<devname>/brport later, if sysfs is enabled. */
-	p->kobj.kset = NULL;
-	kobject_init(&p->kobj, &brport_ktype);
-
-	dp_ifinfo_notify(RTM_NEWLINK, p);
+	dp_ifinfo_notify(RTM_NEWLINK, vport);
 
 	return 0;
 }
@@ -437,7 +411,7 @@ static int attach_port(int dp_idx, struct odp_port __user *portp)
 	goto out_unlock_dp;
 
 got_port_no:
-	err = new_dp_port(dp, &port, port_no);
+	err = new_vport(dp, &port, port_no);
 	if (err)
 		goto out_unlock_dp;
 
@@ -454,9 +428,8 @@ out:
 	return err;
 }
 
-int dp_detach_port(struct dp_port *p)
+int dp_detach_port(struct vport *p)
 {
-	struct vport *vport = p->vport;
 	int err;
 
 	ASSERT_RTNL();
@@ -470,7 +443,7 @@ int dp_detach_port(struct dp_port *p)
 	list_del_rcu(&p->node);
 	rcu_assign_pointer(p->dp->ports[p->port_no], NULL);
 
-	err = vport_detach(vport);
+	err = vport_detach(p);
 	if (err)
 		return err;
 
@@ -478,17 +451,15 @@ int dp_detach_port(struct dp_port *p)
 	synchronize_rcu();
 
 	vport_lock();
-	vport_del(vport);
+	vport_del(p);
 	vport_unlock();
 
-	kobject_put(&p->kobj);
-
 	return 0;
 }
 
 static int detach_port(int dp_idx, int port_no)
 {
-	struct dp_port *p;
+	struct vport *p;
 	struct datapath *dp;
 	int err;
 
@@ -526,7 +497,7 @@ static void suppress_loop(struct datapath *dp, struct sw_flow_actions *actions)
 }
 
 /* Must be called with rcu_read_lock. */
-void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
+void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 {
 	struct datapath *dp = p->dp;
 	struct dp_stats_percpu *stats;
@@ -538,7 +509,7 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
 	struct loop_counter *loop;
 	int error;
 
-	OVS_CB(skb)->dp_port = p;
+	OVS_CB(skb)->vport = p;
 
 	/* Extract flow from 'skb' into 'key'. */
 	error = flow_extract(skb, p ? p->port_no : ODPP_NONE, &key);
@@ -775,8 +746,8 @@ static int queue_control_packets(struct sk_buff *skb, struct sk_buff_head *queue
 	int port_no;
 	int err;
 
-	if (OVS_CB(skb)->dp_port)
-		port_no = OVS_CB(skb)->dp_port->port_no;
+	if (OVS_CB(skb)->vport)
+		port_no = OVS_CB(skb)->vport->port_no;
 	else
 		port_no = ODPP_LOCAL;
 
@@ -1333,9 +1304,9 @@ static int do_execute(struct datapath *dp, const struct odp_execute *execute)
 		goto error_free_actions;
 
 	if (execute->in_port < DP_MAX_PORTS)
-		OVS_CB(skb)->dp_port = dp->ports[execute->in_port];
+		OVS_CB(skb)->vport = dp->ports[execute->in_port];
 	else
-		OVS_CB(skb)->dp_port = NULL;
+		OVS_CB(skb)->vport = NULL;
 
 	err = -EFAULT;
 	if (copy_from_user(skb_put(skb, execute->length), execute->data,
@@ -1421,7 +1392,7 @@ static int get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
 /* MTU of the dp pseudo-device: ETH_DATA_LEN or the minimum of the ports */
 int dp_min_mtu(const struct datapath *dp)
 {
-	struct dp_port *p;
+	struct vport *p;
 	int mtu = 0;
 
 	ASSERT_RTNL();
@@ -1431,10 +1402,10 @@ int dp_min_mtu(const struct datapath *dp)
 
 		/* Skip any internal ports, since that's what we're trying to
 		 * set. */
-		if (is_internal_vport(p->vport))
+		if (is_internal_vport(p))
 			continue;
 
-		dev_mtu = vport_get_mtu(p->vport);
+		dev_mtu = vport_get_mtu(p);
 		if (!mtu || dev_mtu < mtu)
 			mtu = dev_mtu;
 	}
@@ -1446,7 +1417,7 @@ int dp_min_mtu(const struct datapath *dp)
  * be called with RTNL lock. */
 void set_internal_devs_mtu(const struct datapath *dp)
 {
-	struct dp_port *p;
+	struct vport *p;
 	int mtu;
 
 	ASSERT_RTNL();
@@ -1454,20 +1425,20 @@ void set_internal_devs_mtu(const struct datapath *dp)
 	mtu = dp_min_mtu(dp);
 
 	list_for_each_entry_rcu (p, &dp->port_list, node) {
-		if (is_internal_vport(p->vport))
-			vport_set_mtu(p->vport, mtu);
+		if (is_internal_vport(p))
+			vport_set_mtu(p, mtu);
 	}
 }
 
-static int put_port(const struct dp_port *p, struct odp_port __user *uop)
+static int put_port(const struct vport *p, struct odp_port __user *uop)
 {
 	struct odp_port op;
 
 	memset(&op, 0, sizeof op);
 
 	rcu_read_lock();
-	strncpy(op.devname, vport_get_name(p->vport), sizeof op.devname);
-	strncpy(op.type, vport_get_type(p->vport), sizeof op.type);
+	strncpy(op.devname, vport_get_name(p), sizeof op.devname);
+	strncpy(op.type, vport_get_type(p), sizeof op.type);
 	rcu_read_unlock();
 
 	op.port = p->port_no;
@@ -1484,7 +1455,6 @@ static int query_port(struct datapath *dp, struct odp_port __user *uport)
 
 	if (port.devname[0]) {
 		struct vport *vport;
-		struct dp_port *dp_port;
 		int err = 0;
 
 		port.devname[IFNAMSIZ - 1] = '\0';
@@ -1497,14 +1467,12 @@ static int query_port(struct datapath *dp, struct odp_port __user *uport)
 			err = -ENODEV;
 			goto error_unlock;
 		}
-
-		dp_port = vport_get_dp_port(vport);
-		if (!dp_port || dp_port->dp != dp) {
+		if (vport->dp != dp) {
 			err = -ENOENT;
 			goto error_unlock;
 		}
 
-		port.port = dp_port->port_no;
+		port.port = vport->port_no;
 
 error_unlock:
 		rcu_read_unlock();
@@ -1527,7 +1495,7 @@ static int do_list_ports(struct datapath *dp, struct odp_port __user *uports,
 {
 	int idx = 0;
 	if (n_ports) {
-		struct dp_port *p;
+		struct vport *p;
 
 		list_for_each_entry_rcu (p, &dp->port_list, node) {
 			if (put_port(p, &uports[idx]))
diff --git a/datapath/datapath.h b/datapath/datapath.h
index adc573f..3a71709 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -23,7 +23,6 @@
 #include "dp_sysfs.h"
 
 struct vport;
-struct dp_port;
 
 /* Mask for the priority bits in a vlan header.  If we ever merge upstream
  * then this should go into include/linux/if_vlan.h. */
@@ -75,7 +74,7 @@ struct dp_port_group {
  * @table: Current flow table (RCU protected).
  * @groups: Port groups, used by ODPAT_OUTPUT_GROUP action (RCU protected).
  * @n_ports: Number of ports currently in @ports.
- * @ports: Map from port number to &struct dp_port.  %ODPP_LOCAL port
+ * @ports: Map from port number to &struct vport.  %ODPP_LOCAL port
  * always exists, other ports may be %NULL.
  * @port_list: List of all ports in @ports in arbitrary order.
  * @stats_percpu: Per-CPU datapath statistics.
@@ -102,7 +101,7 @@ struct datapath {
 
 	/* Switch ports. */
 	unsigned int n_ports;
-	struct dp_port *ports[DP_MAX_PORTS];
+	struct vport *ports[DP_MAX_PORTS];
 	struct list_head port_list;
 
 	/* Stats. */
@@ -112,30 +111,6 @@ struct datapath {
 	unsigned int sflow_probability;
 };
 
-/**
- * struct dp_port - one port within a datapath
- * @port_no: Index into @dp's @ports array.
- * @dp: Datapath to which this port belongs.
- * @vport: The network device attached to this port.  The contents depends on
- * the device and should be accessed only through the vport_* functions.
- * @kobj: Represents /sys/class/net/<devname>/brport.
- * @linkname: The name of the link from /sys/class/net/<datapath>/brif to this
- * &struct dp_port.  (We keep this around so that we can delete it if the
- * device gets renamed.)  Set to the null string when no link exists.
- * @node: Element in @dp's @port_list.
- * @sflow_pool: Number of packets that were candidates for sFlow sampling,
- * regardless of whether they were actually chosen and sent down to userspace.
- */
-struct dp_port {
-	u16 port_no;
-	struct datapath	*dp;
-	struct vport *vport;
-	struct kobject kobj;
-	char linkname[IFNAMSIZ];
-	struct list_head node;
-	atomic_t sflow_pool;
-};
-
 enum csum_type {
 	OVS_CSUM_NONE = 0,
 	OVS_CSUM_UNNECESSARY = 1,
@@ -145,7 +120,7 @@ enum csum_type {
 
 /**
  * struct ovs_skb_cb - OVS data in skb CB
- * @dp_port: The datapath port on which the skb entered the switch.
+ * @vport: The datapath port on which the skb entered the switch.
  * @ip_summed: Consistently stores L4 checksumming status across different
  * kernel versions.
  * @tun_id: ID (in network byte order) of the tunnel that encapsulated this
@@ -153,7 +128,7 @@ enum csum_type {
  * @is_frag: %true if this packet is an IPv4 fragment, %false otherwise.
  */
 struct ovs_skb_cb {
-	struct dp_port		*dp_port;
+	struct vport		*vport;
 	enum csum_type		ip_summed;
 	__be32			tun_id;
 	bool			is_frag;
@@ -163,8 +138,8 @@ struct ovs_skb_cb {
 extern struct notifier_block dp_device_notifier;
 extern int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
 
-void dp_process_received_packet(struct dp_port *, struct sk_buff *);
-int dp_detach_port(struct dp_port *);
+void dp_process_received_packet(struct vport *, struct sk_buff *);
+int dp_detach_port(struct vport *);
 int dp_output_control(struct datapath *, struct sk_buff *, int, u32 arg);
 int dp_min_mtu(const struct datapath *dp);
 void set_internal_devs_mtu(const struct datapath *dp);
diff --git a/datapath/dp_notify.c b/datapath/dp_notify.c
index 1843d75..e7d08bc 100644
--- a/datapath/dp_notify.c
+++ b/datapath/dp_notify.c
@@ -19,7 +19,6 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
 {
 	struct net_device *dev = ptr;
 	struct vport *vport;
-	struct dp_port *p;
 	struct datapath *dp;
 
 	if (is_internal_dev(dev))
@@ -30,24 +29,20 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event,
 	if (!vport)
 		return NOTIFY_DONE;
 
-	p = vport_get_dp_port(vport);
-
-	if (!p)
-		return NOTIFY_DONE;
-	dp = p->dp;
+	dp = vport->dp;
 
 	switch (event) {
 	case NETDEV_UNREGISTER:
 		mutex_lock(&dp->mutex);
-		dp_detach_port(p);
+		dp_detach_port(vport);
 		mutex_unlock(&dp->mutex);
 		break;
 
 	case NETDEV_CHANGENAME:
-		if (p->port_no != ODPP_LOCAL) {
+		if (vport->port_no != ODPP_LOCAL) {
 			mutex_lock(&dp->mutex);
-			dp_sysfs_del_if(p);
-			dp_sysfs_add_if(p);
+			dp_sysfs_del_if(vport);
+			dp_sysfs_add_if(vport);
 			mutex_unlock(&dp->mutex);
 		}
 		break;
diff --git a/datapath/dp_sysfs.h b/datapath/dp_sysfs.h
index 2d688ac..49af58a 100644
--- a/datapath/dp_sysfs.h
+++ b/datapath/dp_sysfs.h
@@ -10,15 +10,15 @@
 #define DP_SYSFS_H 1
 
 struct datapath;
-struct dp_port;
+struct vport;
 
 /* dp_sysfs_dp.c */
 int dp_sysfs_add_dp(struct datapath *dp);
 int dp_sysfs_del_dp(struct datapath *dp);
 
 /* dp_sysfs_if.c */
-int dp_sysfs_add_if(struct dp_port *p);
-int dp_sysfs_del_if(struct dp_port *p);
+int dp_sysfs_add_if(struct vport *p);
+int dp_sysfs_del_if(struct vport *p);
 
 #ifdef CONFIG_SYSFS
 extern struct sysfs_ops brport_sysfs_ops;
diff --git a/datapath/dp_sysfs_dp.c b/datapath/dp_sysfs_dp.c
index 4abe4fb..413dfc3 100644
--- a/datapath/dp_sysfs_dp.c
+++ b/datapath/dp_sysfs_dp.c
@@ -46,16 +46,7 @@
 struct datapath *sysfs_get_dp(struct net_device *netdev)
 {
 	struct vport *vport = internal_dev_get_vport(netdev);
-	struct dp_port *dp_port;
-
-	if (!vport)
-		return NULL;
-
-	dp_port = vport_get_dp_port(vport);
-	if (!dp_port)
-		return NULL;
-
-	return dp_port->dp;
+	return vport ? vport->dp : NULL;
 }
 /*
  * Common code for storing bridge parameters.
@@ -359,7 +350,7 @@ static struct attribute_group bridge_group = {
  */
 int dp_sysfs_add_dp(struct datapath *dp)
 {
-	struct kobject *kobj = vport_get_kobj(dp->ports[ODPP_LOCAL]->vport);
+	struct kobject *kobj = vport_get_kobj(dp->ports[ODPP_LOCAL]);
 	int err;
 
 	/* Create /sys/class/net/<devname>/bridge directory. */
@@ -388,7 +379,7 @@ int dp_sysfs_add_dp(struct datapath *dp)
 
 int dp_sysfs_del_dp(struct datapath *dp)
 {
-	struct kobject *kobj = vport_get_kobj(dp->ports[ODPP_LOCAL]->vport);
+	struct kobject *kobj = vport_get_kobj(dp->ports[ODPP_LOCAL]);
 
 	kobject_del(&dp->ifobj);
 	sysfs_remove_group(kobj, &bridge_group);
@@ -398,6 +389,6 @@ int dp_sysfs_del_dp(struct datapath *dp)
 #else /* !CONFIG_SYSFS */
 int dp_sysfs_add_dp(struct datapath *dp) { return 0; }
 int dp_sysfs_del_dp(struct datapath *dp) { return 0; }
-int dp_sysfs_add_if(struct dp_port *p) { return 0; }
-int dp_sysfs_del_if(struct dp_port *p) { return 0; }
+int dp_sysfs_add_if(struct vport *p) { return 0; }
+int dp_sysfs_del_if(struct vport *p) { return 0; }
 #endif /* !CONFIG_SYSFS */
diff --git a/datapath/dp_sysfs_if.c b/datapath/dp_sysfs_if.c
index b40523a..ac86ac3 100644
--- a/datapath/dp_sysfs_if.c
+++ b/datapath/dp_sysfs_if.c
@@ -26,8 +26,8 @@
 
 struct brport_attribute {
 	struct attribute	attr;
-	ssize_t (*show)(struct dp_port *, char *);
-	ssize_t (*store)(struct dp_port *, unsigned long);
+	ssize_t (*show)(struct vport *, char *);
+	ssize_t (*store)(struct vport *, unsigned long);
 };
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
@@ -49,98 +49,98 @@ struct brport_attribute brport_attr_##_name = { 	        \
 };
 #endif
 
-static ssize_t show_path_cost(struct dp_port *p, char *buf)
+static ssize_t show_path_cost(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
-static ssize_t store_path_cost(struct dp_port *p, unsigned long v)
+static ssize_t store_path_cost(struct vport *p, unsigned long v)
 {
 	return 0;
 }
 static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
 		   show_path_cost, store_path_cost);
 
-static ssize_t show_priority(struct dp_port *p, char *buf)
+static ssize_t show_priority(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
-static ssize_t store_priority(struct dp_port *p, unsigned long v)
+static ssize_t store_priority(struct vport *p, unsigned long v)
 {
 	return 0;
 }
 static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
 			 show_priority, store_priority);
 
-static ssize_t show_designated_root(struct dp_port *p, char *buf)
+static ssize_t show_designated_root(struct vport *p, char *buf)
 {
 	return sprintf(buf, "0000.010203040506\n");
 }
 static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
 
-static ssize_t show_designated_bridge(struct dp_port *p, char *buf)
+static ssize_t show_designated_bridge(struct vport *p, char *buf)
 {
 	return sprintf(buf, "0000.060504030201\n");
 }
 static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
 
-static ssize_t show_designated_port(struct dp_port *p, char *buf)
+static ssize_t show_designated_port(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
 
-static ssize_t show_designated_cost(struct dp_port *p, char *buf)
+static ssize_t show_designated_cost(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
 
-static ssize_t show_port_id(struct dp_port *p, char *buf)
+static ssize_t show_port_id(struct vport *p, char *buf)
 {
 	return sprintf(buf, "0x%x\n", 0);
 }
 static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
 
-static ssize_t show_port_no(struct dp_port *p, char *buf)
+static ssize_t show_port_no(struct vport *p, char *buf)
 {
 	return sprintf(buf, "0x%x\n", p->port_no);
 }
 
 static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
 
-static ssize_t show_change_ack(struct dp_port *p, char *buf)
+static ssize_t show_change_ack(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
 
-static ssize_t show_config_pending(struct dp_port *p, char *buf)
+static ssize_t show_config_pending(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
 
-static ssize_t show_port_state(struct dp_port *p, char *buf)
+static ssize_t show_port_state(struct vport *p, char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
 
-static ssize_t show_message_age_timer(struct dp_port *p,
+static ssize_t show_message_age_timer(struct vport *p,
 					    char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
 
-static ssize_t show_forward_delay_timer(struct dp_port *p,
+static ssize_t show_forward_delay_timer(struct vport *p,
 					    char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
 }
 static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
 
-static ssize_t show_hold_timer(struct dp_port *p,
+static ssize_t show_hold_timer(struct vport *p,
 					    char *buf)
 {
 	return sprintf(buf, "%d\n", 0);
@@ -166,13 +166,13 @@ static struct brport_attribute *brport_attrs[] = {
 };
 
 #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr)
-#define to_brport(obj)	container_of(obj, struct dp_port, kobj)
+#define to_brport(obj)	container_of(obj, struct vport, kobj)
 
 static ssize_t brport_show(struct kobject * kobj,
 			   struct attribute * attr, char * buf)
 {
 	struct brport_attribute * brport_attr = to_brport_attr(attr);
-	struct dp_port * p = to_brport(kobj);
+	struct vport * p = to_brport(kobj);
 
 	return brport_attr->show(p, buf);
 }
@@ -181,7 +181,7 @@ static ssize_t brport_store(struct kobject * kobj,
 			    struct attribute * attr,
 			    const char * buf, size_t count)
 {
-	struct dp_port * p = to_brport(kobj);
+	struct vport * p = to_brport(kobj);
 	ssize_t ret = -EINVAL;
 
 	if (!capable(CAP_NET_ADMIN))
@@ -203,9 +203,9 @@ struct sysfs_ops brport_sysfs_ops = {
  * Creates a brport subdirectory with bridge attributes.
  * Puts symlink in bridge's brport subdirectory
  */
-int dp_sysfs_add_if(struct dp_port *p)
+int dp_sysfs_add_if(struct vport *p)
 {
-	struct kobject *kobj = vport_get_kobj(p->vport);
+	struct kobject *kobj = vport_get_kobj(p);
 	struct datapath *dp = p->dp;
 	struct brport_attribute **a;
 	int err;
@@ -220,7 +220,7 @@ int dp_sysfs_add_if(struct dp_port *p)
 
 	/* Create symlink from /sys/class/net/<devname>/brport/bridge to
 	 * /sys/class/net/<bridgename>. */
-	err = sysfs_create_link(&p->kobj, vport_get_kobj(dp->ports[ODPP_LOCAL]->vport),
+	err = sysfs_create_link(&p->kobj, vport_get_kobj(dp->ports[ODPP_LOCAL]),
 				SYSFS_BRIDGE_PORT_LINK); /* "bridge" */
 	if (err)
 		goto err_del;
@@ -234,10 +234,10 @@ int dp_sysfs_add_if(struct dp_port *p)
 
 	/* Create symlink from /sys/class/net/<bridgename>/brif/<devname> to
 	 * /sys/class/net/<devname>/brport.  */
-	err = sysfs_create_link(&dp->ifobj, &p->kobj, vport_get_name(p->vport));
+	err = sysfs_create_link(&dp->ifobj, &p->kobj, vport_get_name(p));
 	if (err)
 		goto err_del;
-	strcpy(p->linkname, vport_get_name(p->vport));
+	strcpy(p->linkname, vport_get_name(p));
 
 	kobject_uevent(&p->kobj, KOBJ_ADD);
 
@@ -250,7 +250,7 @@ err:
 	return err;
 }
 
-int dp_sysfs_del_if(struct dp_port *p)
+int dp_sysfs_del_if(struct vport *p)
 {
 	if (p->linkname[0]) {
 		sysfs_remove_link(&p->dp->ifobj, p->linkname);
diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c
index a6e7262..b077a8a 100644
--- a/datapath/vport-internal_dev.c
+++ b/datapath/vport-internal_dev.c
@@ -104,16 +104,13 @@ static void internal_dev_getinfo(struct net_device *netdev,
 				 struct ethtool_drvinfo *info)
 {
 	struct vport *vport = internal_dev_get_vport(netdev);
-	struct dp_port *dp_port;
 
 	strcpy(info->driver, "openvswitch");
 
 	if (!vport)
 		return;
 
-	dp_port = vport_get_dp_port(vport);
-	if (dp_port)
-		sprintf(info->bus_info, "%d.%d", dp_port->dp->dp_idx, dp_port->port_no);
+	sprintf(info->bus_info, "%d.%d", vport->dp->dp_idx, vport->port_no);
 }
 
 static struct ethtool_ops internal_dev_ethtool_ops = {
@@ -134,14 +131,8 @@ static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu)
 	if (new_mtu < 68)
 		return -EINVAL;
 
-	if (vport) {
-		struct dp_port *dp_port = vport_get_dp_port(vport);
-
-		if (dp_port) {
-			if (new_mtu > dp_min_mtu(dp_port->dp))
-				return -EINVAL;
-		}
-	}
+	if (vport && vport->dp && new_mtu > dp_min_mtu(vport->dp))
+		return -EINVAL;
 
 	netdev->mtu = new_mtu;
 	return 0;
diff --git a/datapath/vport-patch.c b/datapath/vport-patch.c
index 3f2215c..5ea5e38 100644
--- a/datapath/vport-patch.c
+++ b/datapath/vport-patch.c
@@ -95,11 +95,9 @@ static int set_config(struct vport *vport, __u32 *config)
 
 	strcpy(patch_vport->peer_name, peer_name);
 
-	if (vport_get_dp_port(vport)) {
-		hlist_del(&patch_vport->hash_node);
-		rcu_assign_pointer(patch_vport->peer, vport_locate(patch_vport->peer_name));
-		hlist_add_head(&patch_vport->hash_node, hash_bucket(patch_vport->peer_name));
-	}
+	hlist_del(&patch_vport->hash_node);
+	rcu_assign_pointer(patch_vport->peer, vport_locate(patch_vport->peer_name));
+	hlist_add_head(&patch_vport->hash_node, hash_bucket(patch_vport->peer_name));
 
 	return 0;
 }
diff --git a/datapath/vport.c b/datapath/vport.c
index 2ae0053..2363802 100644
--- a/datapath/vport.c
+++ b/datapath/vport.c
@@ -47,13 +47,12 @@ static struct hlist_head *dev_table;
  * one of these locks if you don't want the vport to be deleted out from under
  * you.
  *
- * If you get a reference to a vport through a dp_port, it is protected
+ * If you get a reference to a vport through a datapath, it is protected
  * by RCU and you need to hold rcu_read_lock instead when reading.
  *
  * If multiple locks are taken, the hierarchy is:
  * 1. RTNL
- * 2. DP
- * 3. vport
+ * 2. vport
  */
 static DEFINE_MUTEX(vport_mutex);
 
@@ -504,6 +503,19 @@ static void unregister_vport(struct vport *vport)
 	hlist_del(&vport->hash_node);
 }
 
+static void release_vport(struct kobject *kobj)
+{
+	struct vport *p = container_of(kobj, struct vport, kobj);
+	kfree(p);
+}
+
+static struct kobj_type brport_ktype = {
+#ifdef CONFIG_SYSFS
+	.sysfs_ops = &brport_sysfs_ops,
+#endif
+	.release = release_vport
+};
+
 /**
  *	vport_alloc - allocate and initialize new vport
  *
@@ -530,8 +542,14 @@ struct vport *vport_alloc(int priv_size, const struct vport_ops *ops)
 	if (!vport)
 		return ERR_PTR(-ENOMEM);
 
+	atomic_set(&vport->sflow_pool, 0);
 	vport->ops = ops;
 
+	/* Initialize kobject for bridge.  This will be added as
+	 * /sys/class/net/<devname>/brport later, if sysfs is enabled. */
+	vport->kobj.kset = NULL;
+	kobject_init(&vport->kobj, &brport_ktype);
+
 	if (vport->ops->flags & VPORT_F_GEN_STATS) {
 		vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
 		if (!vport->percpu_stats)
@@ -555,7 +573,7 @@ void vport_free(struct vport *vport)
 	if (vport->ops->flags & VPORT_F_GEN_STATS)
 		free_percpu(vport->percpu_stats);
 
-	kfree(vport);
+	kobject_put(&vport->kobj);
 }
 
 /**
@@ -627,7 +645,6 @@ int vport_del(struct vport *vport)
 {
 	ASSERT_RTNL();
 	ASSERT_VPORT();
-	BUG_ON(vport_get_dp_port(vport));
 
 	unregister_vport(vport);
 
@@ -635,32 +652,19 @@ int vport_del(struct vport *vport)
 }
 
 /**
- *	vport_attach - attach a vport to a datapath
+ *	vport_attach - notify a vport that it has been attached to a datapath
  *
  * @vport: vport to attach.
- * @dp_port: Datapath port to attach the vport to.
  *
- * Attaches a vport to a specific datapath so that packets may be exchanged.
- * Both ports must be currently unattached.  @dp_port must be successfully
- * attached to a vport before it is connected to a datapath and must not be
- * modified while connected.  RTNL lock and the appropriate DP mutex must be held.
+ * Performs vport-specific actions so that packets may be exchanged.  RTNL lock
+ * and the appropriate DP mutex must be held.
  */
-int vport_attach(struct vport *vport, struct dp_port *dp_port)
+int vport_attach(struct vport *vport)
 {
 	ASSERT_RTNL();
 
-	if (vport_get_dp_port(vport))
-		return -EBUSY;
-
-	if (vport->ops->attach) {
-		int err;
-
-		err = vport->ops->attach(vport);
-		if (err)
-			return err;
-	}
-
-	rcu_assign_pointer(vport->dp_port, dp_port);
+	if (vport->ops->attach)
+		return vport->ops->attach(vport);
 
 	return 0;
 }
@@ -670,25 +674,17 @@ int vport_attach(struct vport *vport, struct dp_port *dp_port)
  *
  * @vport: vport to detach.
  *
- * Detaches a vport from a datapath.  May fail for a variety of reasons,
- * including lack of memory.  RTNL lock and the appropriate DP mutex must be held.
+ * Performs vport-specific actions before a vport is detached from a datapath.
+ * May fail for a variety of reasons, including lack of memory.  RTNL lock and
+ * the appropriate DP mutex must be held.
  */
 int vport_detach(struct vport *vport)
 {
-	struct dp_port *dp_port;
-
 	ASSERT_RTNL();
 
-	dp_port = vport_get_dp_port(vport);
-	if (!dp_port)
-		return -EINVAL;
-
-	rcu_assign_pointer(vport->dp_port, NULL);
-
 	if (vport->ops->detach)
 		return vport->ops->detach(vport);
-	else
-		return 0;
+	return 0;
 }
 
 /**
@@ -713,12 +709,8 @@ int vport_set_mtu(struct vport *vport, int mtu)
 
 		ret = vport->ops->set_mtu(vport, mtu);
 
-		if (!ret && !is_internal_vport(vport)) {
-			struct dp_port *dp_port = vport_get_dp_port(vport);
-
-			if (dp_port)
-				set_internal_devs_mtu(dp_port->dp);
-		}
+		if (!ret && !is_internal_vport(vport))
+			set_internal_devs_mtu(vport->dp);
 
 		return ret;
 	} else
@@ -816,20 +808,6 @@ const unsigned char *vport_get_addr(const struct vport *vport)
 }
 
 /**
- *	vport_get_dp_port - retrieve attached datapath port
- *
- * @vport: vport from which to retrieve the datapath port.
- *
- * Retrieves the attached datapath port or null if not attached.  Either RTNL
- * lock or rcu_read_lock must be held for the entire duration that the datapath
- * port is being accessed.
- */
-struct dp_port *vport_get_dp_port(const struct vport *vport)
-{
-	return rcu_dereference(vport->dp_port);
-}
-
-/**
  *	vport_get_kobj - retrieve associated kobj
  *
  * @vport: vport from which to retrieve the associated kobj
@@ -989,18 +967,12 @@ unsigned char vport_get_operstate(const struct vport *vport)
  */
 int vport_get_ifindex(const struct vport *vport)
 {
-	const struct dp_port *dp_port;
-
 	if (vport->ops->get_ifindex)
 		return vport->ops->get_ifindex(vport);
 
 	/* If we don't actually have an ifindex, use the local port's.
 	 * Userspace doesn't check it anyways. */
-	dp_port = vport_get_dp_port(vport);
-	if (!dp_port)
-		return -EAGAIN;
-
-	return vport_get_ifindex(dp_port->dp->ports[ODPP_LOCAL]->vport);
+	return vport_get_ifindex(vport->dp->ports[ODPP_LOCAL]);
 }
 
 /**
@@ -1049,15 +1021,6 @@ int vport_get_mtu(const struct vport *vport)
  */
 void vport_receive(struct vport *vport, struct sk_buff *skb)
 {
-	struct dp_port *dp_port = vport_get_dp_port(vport);
-
-	if (!dp_port) {
-		vport_record_error(vport, VPORT_E_RX_DROPPED);
-		kfree_skb(skb);
-
-		return;
-	}
-
 	if (vport->ops->flags & VPORT_F_GEN_STATS) {
 		struct vport_percpu_stats *stats;
 
@@ -1075,7 +1038,7 @@ void vport_receive(struct vport *vport, struct sk_buff *skb)
 	if (!(vport->ops->flags & VPORT_F_TUN_ID))
 		OVS_CB(skb)->tun_id = 0;
 
-	dp_process_received_packet(dp_port, skb);
+	dp_process_received_packet(vport, skb);
 }
 
 static inline unsigned packet_length(const struct sk_buff *skb)
@@ -1106,8 +1069,7 @@ int vport_send(struct vport *vport, struct sk_buff *skb)
 	if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
 		if (net_ratelimit())
 			pr_warn("%s: dropped over-mtu packet: %d > %d\n",
-				dp_name(vport_get_dp_port(vport)->dp),
-				packet_length(skb), mtu);
+				dp_name(vport->dp), packet_length(skb), mtu);
 		goto error;
 	}
 
diff --git a/datapath/vport.h b/datapath/vport.h
index 792e8b6..8e9c65a 100644
--- a/datapath/vport.h
+++ b/datapath/vport.h
@@ -19,7 +19,6 @@
 #include "odp-compat.h"
 
 struct vport;
-struct dp_port;
 
 /* The following definitions are for users of the vport subsytem: */
 
@@ -49,7 +48,7 @@ int vport_del(struct vport *);
 
 struct vport *vport_locate(const char *name);
 
-int vport_attach(struct vport *, struct dp_port *);
+int vport_attach(struct vport *);
 int vport_detach(struct vport *);
 
 int vport_set_mtu(struct vport *, int mtu);
@@ -60,7 +59,6 @@ const char *vport_get_name(const struct vport *);
 const char *vport_get_type(const struct vport *);
 const unsigned char *vport_get_addr(const struct vport *);
 
-struct dp_port *vport_get_dp_port(const struct vport *);
 struct kobject *vport_get_kobj(const struct vport *);
 int vport_get_stats(struct vport *, struct odp_vport_stats *);
 
@@ -96,10 +94,28 @@ struct vport_err_stats {
 	u64 collisions;
 };
 
+/**
+ * struct vport - one port within a datapath
+ * @port_no: Index into @dp's @ports array.
+ * @dp: Datapath to which this port belongs.
+ * @kobj: Represents /sys/class/net/<devname>/brport.
+ * @linkname: The name of the link from /sys/class/net/<datapath>/brif to this
+ * &struct vport.  (We keep this around so that we can delete it if the
+ * device gets renamed.)  Set to the null string when no link exists.
+ * @node: Element in @dp's @port_list.
+ * @sflow_pool: Number of packets that were candidates for sFlow sampling,
+ * regardless of whether they were actually chosen and sent down to userspace.
+ */
 struct vport {
+	u16 port_no;
+	struct datapath	*dp;
+	struct kobject kobj;
+	char linkname[IFNAMSIZ];
+	struct list_head node;
+	atomic_t sflow_pool;
+
 	struct hlist_node hash_node;
 	const struct vport_ops *ops;
-	struct dp_port *dp_port;
 
 	struct vport_percpu_stats *percpu_stats;
 
-- 
1.7.1





More information about the dev mailing list