[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