datapath: Merge "struct dp_port" into "struct vport".
authorBen Pfaff <blp@nicira.com>
Fri, 3 Dec 2010 21:09:26 +0000 (13:09 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 3 Dec 2010 22:43:38 +0000 (14:43 -0800)
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@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
13 files changed:
datapath/actions.c
datapath/datapath.c
datapath/datapath.h
datapath/dp_notify.c
datapath/dp_sysfs.h
datapath/dp_sysfs_dp.c
datapath/dp_sysfs_if.c
datapath/tunnel.c
datapath/vport-internal_dev.c
datapath/vport-netdev.c
datapath/vport-patch.c
datapath/vport.c
datapath/vport.h

index 5904c83..41812a4 100644 (file)
@@ -368,7 +368,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;
@@ -377,7 +377,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:
@@ -396,7 +396,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,
-                        struct dp_port *dp_port)
+                        struct vport *vport)
 {
        struct odp_sflow_sample_header *hdr;
        unsigned int actlen = n_actions * sizeof(union odp_action);
@@ -410,7 +410,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);
 }
 
@@ -428,7 +428,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 ||
index dc91fec..382a8c2 100644 (file)
@@ -63,13 +63,13 @@ 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];
 static DEFINE_MUTEX(dp_mutex);
 
-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)
@@ -95,7 +95,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)
@@ -110,12 +110,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;
 
@@ -134,21 +134,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);
@@ -160,7 +159,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;
@@ -253,7 +252,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;
@@ -291,7 +290,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)
@@ -334,30 +333,18 @@ 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_parms parms;
        struct vport *vport;
-       struct dp_port *p;
        int err;
 
        parms.name = odp_port->devname;
        parms.type = odp_port->type;
        parms.config = odp_port->config;
+       parms.dp = dp;
+       parms.port_no = port_no;
 
        vport_lock();
        vport = vport_add(&parms);
@@ -366,31 +353,17 @@ 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);
-
-       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;
 }
@@ -421,7 +394,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;
 
@@ -438,9 +411,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();
@@ -454,7 +426,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;
 
@@ -462,17 +434,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;
 
@@ -502,7 +472,7 @@ out:
 }
 
 /* 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;
@@ -511,7 +481,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;
 
        if (!OVS_CB(skb)->flow) {
                struct odp_flow_key key;
@@ -757,8 +727,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;
 
@@ -1382,7 +1352,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();
@@ -1392,10 +1362,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;
        }
@@ -1407,7 +1377,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();
@@ -1415,20 +1385,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;
@@ -1445,7 +1415,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';
@@ -1458,14 +1427,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();
@@ -1488,7 +1455,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]))
index 36accfd..07406da 100644 (file)
@@ -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. */
@@ -67,7 +66,7 @@ struct dp_stats_percpu {
  * @n_flows: Number of flows currently in flow table.
  * @table: Current flow table (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.
@@ -91,7 +90,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. */
@@ -101,30 +100,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,
@@ -134,7 +109,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.
  * @flow: The flow associated with this packet.  May be %NULL if no flow.
  * @ip_summed: Consistently stores L4 checksumming status across different
  * kernel versions.
@@ -142,7 +117,7 @@ enum csum_type {
  * packet. It is 0 if the packet was not received on a tunnel.
  */
 struct ovs_skb_cb {
-       struct dp_port          *dp_port;
+       struct vport            *vport;
        struct sw_flow          *flow;
        enum csum_type          ip_summed;
        __be32                  tun_id;
@@ -152,8 +127,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);
index 1843d75..e7d08bc 100644 (file)
@@ -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;
index 2d688ac..49af58a 100644 (file)
 #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;
index 4abe4fb..413dfc3 100644 (file)
 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 */
index b40523a..fc7c2d8 100644 (file)
@@ -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);
@@ -165,14 +165,14 @@ static struct brport_attribute *brport_attrs[] = {
        NULL
 };
 
-#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_vport_attr(_at) container_of(_at, struct brport_attribute, attr)
+#define to_vport(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 brport_attribute * brport_attr = to_vport_attr(attr);
+       struct vport * p = to_vport(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_vport(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);
index b6bd6f6..37ec4d9 100644 (file)
@@ -883,22 +883,17 @@ static struct tnl_cache *build_cache(struct vport *vport,
 #endif
 
        if (is_internal_dev(rt_dst(rt).dev)) {
-               int err;
+               struct odp_flow_key flow_key;
+               struct tbl_node *flow_node;
                struct vport *vport;
-               struct dp_port *dp_port;
                struct sk_buff *skb;
                bool is_frag;
-               struct odp_flow_key flow_key;
-               struct tbl_node *flow_node;
+               int err;
 
                vport = internal_dev_get_vport(rt_dst(rt).dev);
                if (!vport)
                        goto done;
 
-               dp_port = vport_get_dp_port(vport);
-               if (!dp_port)
-                       goto done;
-
                skb = alloc_skb(cache->len, GFP_ATOMIC);
                if (!skb)
                        goto done;
@@ -906,13 +901,13 @@ static struct tnl_cache *build_cache(struct vport *vport,
                __skb_put(skb, cache->len);
                memcpy(skb->data, get_cached_header(cache), cache->len);
 
-               err = flow_extract(skb, dp_port->port_no, &flow_key, &is_frag);
+               err = flow_extract(skb, vport->port_no, &flow_key, &is_frag);
 
                kfree_skb(skb);
                if (err || is_frag)
                        goto done;
 
-               flow_node = tbl_lookup(rcu_dereference(dp_port->dp->table),
+               flow_node = tbl_lookup(rcu_dereference(vport->dp->table),
                                       &flow_key, flow_hash(&flow_key),
                                       flow_cmp);
                if (flow_node) {
@@ -1352,7 +1347,7 @@ struct vport *tnl_create(const struct vport_parms *parms,
        int initial_frag_id;
        int err;
 
-       vport = vport_alloc(sizeof(struct tnl_vport), vport_ops);
+       vport = vport_alloc(sizeof(struct tnl_vport), vport_ops, parms);
        if (IS_ERR(vport)) {
                err = PTR_ERR(vport);
                goto error;
index c4de2be..c0e250d 100644 (file)
@@ -97,16 +97,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 const struct ethtool_ops internal_dev_ethtool_ops = {
@@ -127,14 +124,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 && new_mtu > dp_min_mtu(vport->dp))
+               return -EINVAL;
 
        netdev->mtu = new_mtu;
        return 0;
@@ -194,7 +185,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
        struct internal_dev *internal_dev;
        int err;
 
-       vport = vport_alloc(sizeof(struct netdev_vport), &internal_vport_ops);
+       vport = vport_alloc(sizeof(struct netdev_vport), &internal_vport_ops, parms);
        if (IS_ERR(vport)) {
                err = PTR_ERR(vport);
                goto error;
index 33fe9a5..c97e0a0 100644 (file)
@@ -94,7 +94,7 @@ static struct vport *netdev_create(const struct vport_parms *parms)
        struct netdev_vport *netdev_vport;
        int err;
 
-       vport = vport_alloc(sizeof(struct netdev_vport), &netdev_vport_ops);
+       vport = vport_alloc(sizeof(struct netdev_vport), &netdev_vport_ops, parms);
        if (IS_ERR(vport)) {
                err = PTR_ERR(vport);
                goto error;
index b5276b1..4b5137d 100644 (file)
@@ -95,12 +95,6 @@ static int set_config(struct vport *vport, const void *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));
-       }
-
        return 0;
 }
 
@@ -110,7 +104,7 @@ static struct vport *patch_create(const struct vport_parms *parms)
        struct patch_vport *patch_vport;
        int err;
 
-       vport = vport_alloc(sizeof(struct patch_vport), &patch_vport_ops);
+       vport = vport_alloc(sizeof(struct patch_vport), &patch_vport_ops, parms);
        if (IS_ERR(vport)) {
                err = PTR_ERR(vport);
                goto error;
@@ -146,7 +140,15 @@ error:
 
 static int patch_modify(struct vport *vport, struct odp_port *port)
 {
-       return set_config(vport, port->config);
+       int err = set_config(vport, port->config);
+       if (!err) {
+               struct patch_vport *patch_vport = patch_vport_priv(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));
+       }
+       return err;
 }
 
 static int patch_destroy(struct vport *vport)
index 2723244..ee80645 100644 (file)
@@ -47,7 +47,7 @@ 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:
@@ -497,6 +497,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
  *
@@ -508,7 +521,7 @@ static void unregister_vport(struct vport *vport)
  * vport_priv().  vports that are no longer needed should be released with
  * vport_free().
  */
-struct vport *vport_alloc(int priv_size, const struct vport_ops *ops)
+struct vport *vport_alloc(int priv_size, const struct vport_ops *ops, const struct vport_parms *parms)
 {
        struct vport *vport;
        size_t alloc_size;
@@ -523,8 +536,16 @@ struct vport *vport_alloc(int priv_size, const struct vport_ops *ops)
        if (!vport)
                return ERR_PTR(-ENOMEM);
 
+       vport->dp = parms->dp;
+       vport->port_no = parms->port_no;
+       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)
@@ -548,7 +569,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);
 }
 
 /**
@@ -620,7 +641,6 @@ int vport_del(struct vport *vport)
 {
        ASSERT_RTNL();
        ASSERT_VPORT();
-       BUG_ON(vport_get_dp_port(vport));
 
        unregister_vport(vport);
 
@@ -628,32 +648,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;
 }
@@ -663,25 +670,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;
 }
 
 /**
@@ -706,12 +705,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
@@ -808,20 +803,6 @@ const unsigned char *vport_get_addr(const struct vport *vport)
        return vport->ops->get_addr(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
  *
@@ -990,18 +971,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]);
 }
 
 /**
@@ -1050,15 +1025,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;
 
@@ -1079,7 +1045,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)
@@ -1110,8 +1076,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;
        }
 
index 7251b4c..f49ecc8 100644 (file)
@@ -20,7 +20,6 @@
 
 struct vport;
 struct vport_parms;
-struct dp_port;
 
 /* The following definitions are for users of the vport subsytem: */
 
@@ -45,7 +44,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);
@@ -56,7 +55,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 rtnl_link_stats64 *);
 
@@ -88,10 +86,37 @@ struct vport_err_stats {
        u64 tx_errors;
 };
 
+/**
+ * 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.
+ * @hash_node: Element in @dev_table hash table in vport.c.
+ * @ops: Class structure.
+ * @percpu_stats: Points to per-CPU statistics used and maintained by the vport
+ * code if %VPORT_F_GEN_STATS is set to 1 in @ops flags, otherwise unused.
+ * @stats_lock: Protects @err_stats and @offset_stats.
+ * @err_stats: Points to error statistics used and maintained by the vport code
+ * if %VPORT_F_GEN_STATS is set to 1 in @ops flags, otherwise unused.
+ * @offset_stats: Added to actual statistics as a sop to compatibility with
+ * XAPI for Citrix XenServer.  Deprecated.
+ */
 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;
 
@@ -112,11 +137,17 @@ struct vport {
  * @type: New vport's type.
  * @config: Kernel copy of 'config' member of &struct odp_port describing
  * configuration for new port.  Exactly %VPORT_CONFIG_SIZE bytes.
+ * @dp: New vport's datapath.
+ * @port_no: New vport's port number.
  */
 struct vport_parms {
        const char *name;
        const char *type;
        const void *config;
+
+       /* For vport_alloc(). */
+       struct datapath *dp;
+       u16 port_no;
 };
 
 /**
@@ -207,7 +238,7 @@ enum vport_err_type {
        VPORT_E_TX_ERROR,
 };
 
-struct vport *vport_alloc(int priv_size, const struct vport_ops *);
+struct vport *vport_alloc(int priv_size, const struct vport_ops *, const struct vport_parms *);
 void vport_free(struct vport *);
 
 #define VPORT_ALIGN 8