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;
if (!p)
goto error;
- vport_send(p->vport, skb);
+ vport_send(p, skb);
return;
error:
* 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);
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);
}
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 ||
* 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)
/* 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)
}
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;
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);
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;
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;
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)
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);
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;
}
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;
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();
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;
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;
}
/* 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;
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;
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;
/* 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();
/* 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;
}
* 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();
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;
if (port.devname[0]) {
struct vport *vport;
- struct dp_port *dp_port;
int err = 0;
port.devname[IFNAMSIZ - 1] = '\0';
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();
{
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]))
#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. */
* @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.
/* 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. */
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,
/**
* 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.
* 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;
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);
{
struct net_device *dev = ptr;
struct vport *vport;
- struct dp_port *p;
struct datapath *dp;
if (is_internal_dev(dev))
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;
#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;
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.
*/
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. */
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);
#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 */
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)
};
#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);
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);
}
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))
* 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;
/* 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;
/* 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);
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);
#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;
__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) {
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;
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 = {
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;
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;
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;
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;
}
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;
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)
* 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:
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
*
* 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;
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)
if (vport->ops->flags & VPORT_F_GEN_STATS)
free_percpu(vport->percpu_stats);
- kfree(vport);
+ kobject_put(&vport->kobj);
}
/**
{
ASSERT_RTNL();
ASSERT_VPORT();
- BUG_ON(vport_get_dp_port(vport));
unregister_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;
}
*
* @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;
}
/**
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
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
*
*/
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]);
}
/**
*/
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;
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)
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;
}
struct vport;
struct vport_parms;
-struct dp_port;
/* The following definitions are for users of the vport subsytem: */
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);
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 *);
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;
* @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;
};
/**
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