#include <linux/mutex.h>
#include <linux/percpu.h>
#include <linux/rtnetlink.h>
+#include <linux/compat.h>
#include "vport.h"
+#include "vport-internal_dev.h"
extern struct vport_ops netdev_vport_ops;
extern struct vport_ops internal_vport_ops;
+extern struct vport_ops patch_vport_ops;
extern struct vport_ops gre_vport_ops;
static struct vport_ops *base_vport_ops_list[] = {
&netdev_vport_ops,
&internal_vport_ops,
+ &patch_vport_ops,
&gre_vport_ops,
};
* on device type). This function is for userspace callers and assumes no
* locks are held.
*/
-int
-vport_add(const struct odp_vport_add __user *uvport_config)
+static int
+do_vport_add(struct odp_vport_add *vport_config)
{
- struct odp_vport_add vport_config;
struct vport *vport;
int err = 0;
- if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_add)))
- return -EFAULT;
-
- vport_config.port_type[VPORT_TYPE_SIZE - 1] = '\0';
- vport_config.devname[IFNAMSIZ - 1] = '\0';
+ vport_config->port_type[VPORT_TYPE_SIZE - 1] = '\0';
+ vport_config->devname[IFNAMSIZ - 1] = '\0';
rtnl_lock();
- vport = vport_locate(vport_config.devname);
+ vport = vport_locate(vport_config->devname);
if (vport) {
err = -EEXIST;
goto out;
}
vport_lock();
- vport = __vport_add(vport_config.devname, vport_config.port_type,
- vport_config.config);
+ vport = __vport_add(vport_config->devname, vport_config->port_type,
+ vport_config->config);
vport_unlock();
if (IS_ERR(vport))
return err;
}
+int
+vport_add(const struct odp_vport_add __user *uvport_config)
+{
+ struct odp_vport_add vport_config;
+
+ if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_add)))
+ return -EFAULT;
+
+ return do_vport_add(&vport_config);
+}
+
+#ifdef CONFIG_COMPAT
+int
+compat_vport_add(struct compat_odp_vport_add *ucompat)
+{
+ struct compat_odp_vport_add compat;
+ struct odp_vport_add vport_config;
+
+ if (copy_from_user(&compat, ucompat, sizeof(struct compat_odp_vport_add)))
+ return -EFAULT;
+
+ memcpy(vport_config.port_type, compat.port_type, VPORT_TYPE_SIZE);
+ memcpy(vport_config.devname, compat.devname, IFNAMSIZ);
+ vport_config.config = compat_ptr(compat.config);
+
+ return do_vport_add(&vport_config);
+}
+#endif
+
/**
* vport_mod - modify existing vport device (for userspace callers)
*
* dependent on device type). This function is for userspace callers and
* assumes no locks are held.
*/
-int
-vport_mod(const struct odp_vport_mod __user *uvport_config)
+static int
+do_vport_mod(struct odp_vport_mod *vport_config)
{
- struct odp_vport_mod vport_config;
struct vport *vport;
int err;
- if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_mod)))
- return -EFAULT;
-
- vport_config.devname[IFNAMSIZ - 1] = '\0';
+ vport_config->devname[IFNAMSIZ - 1] = '\0';
rtnl_lock();
- vport = vport_locate(vport_config.devname);
+ vport = vport_locate(vport_config->devname);
if (!vport) {
err = -ENODEV;
goto out;
}
vport_lock();
- err = __vport_mod(vport, vport_config.config);
+ err = __vport_mod(vport, vport_config->config);
vport_unlock();
out:
return err;
}
+int
+vport_mod(const struct odp_vport_mod __user *uvport_config)
+{
+ struct odp_vport_mod vport_config;
+
+ if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_mod)))
+ return -EFAULT;
+
+ return do_vport_mod(&vport_config);
+}
+
+#ifdef CONFIG_COMPAT
+int
+compat_vport_mod(struct compat_odp_vport_mod *ucompat)
+{
+ struct compat_odp_vport_mod compat;
+ struct odp_vport_mod vport_config;
+
+ if (copy_from_user(&compat, ucompat, sizeof(struct compat_odp_vport_mod)))
+ return -EFAULT;
+
+ memcpy(vport_config.devname, compat.devname, IFNAMSIZ);
+ vport_config.config = compat_ptr(compat.config);
+
+ return do_vport_mod(&vport_config);
+}
+#endif
+
/**
* vport_del - delete existing vport device (for userspace callers)
*
goto out;
}
- if (vport->ops->get_stats)
+ if (vport->ops->get_stats) {
+ rcu_read_lock();
err = vport->ops->get_stats(vport, &stats_req.stats);
- else if (vport->ops->flags & VPORT_F_GEN_STATS) {
+ rcu_read_unlock();
+
+ } else if (vport->ops->flags & VPORT_F_GEN_STATS) {
int i;
memset(&stats_req.stats, 0, sizeof(struct odp_vport_stats));
goto out;
}
+ rcu_read_lock();
memcpy(vport_ether.ether_addr, vport_get_addr(vport), ETH_ALEN);
+ rcu_read_unlock();
out:
vport_unlock();
dump_stack();
}
+ rcu_read_lock();
+
hlist_for_each_entry(vport, node, bucket, hash_node)
if (!strcmp(name, vport_get_name(vport)))
- return vport;
+ goto out;
- return NULL;
+ vport = NULL;
+
+out:
+ rcu_read_unlock();
+ return vport;
}
static void
if (mtu < 68)
return -EINVAL;
- if (vport->ops->set_mtu)
- return vport->ops->set_mtu(vport, mtu);
- else
+ if (vport->ops->set_mtu) {
+ int ret;
+
+ 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);
+ }
+
+ return ret;
+ } else
return -EOPNOTSUPP;
}
* @vport: vport that received the packet
* @skb: skb that was received
*
- * Must be called with rcu_read_lock and bottom halves disabled. The packet
- * cannot be shared and skb->data should point to the Ethernet header. The
- * caller must have already called compute_ip_summed() to initialize the
- * checksumming fields.
+ * Must be called with rcu_read_lock. The packet cannot be shared and
+ * skb->data should point to the Ethernet header. The caller must have already
+ * called compute_ip_summed() to initialize the checksumming fields.
*/
void
vport_receive(struct vport *vport, struct sk_buff *skb)
spin_unlock_bh(&vport->err_stats.lock);
}
}
-
-/**
- * vport_gen_ether_addr - generate an Ethernet address
- *
- * @addr: location to store generated address
- *
- * Generates a random Ethernet address for use when creating a device that
- * has no natural address.
- */
-void
-vport_gen_ether_addr(u8 *addr)
-{
- random_ether_addr(addr);
-
- /* Set the OUI to the Nicira one. */
- addr[0] = 0x00;
- addr[1] = 0x23;
- addr[2] = 0x20;
-
- /* Set the top bit to indicate random address. */
- addr[3] |= 0x80;
-}