aboutsummaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2009-08-19 13:03:46 -0700
committerBen Pfaff <blp@nicira.com>2009-08-19 13:03:46 -0700
commit8fef8c7121222233075a03d57db7e0b48d5f6be5 (patch)
tree5cb9822a490c41694be2c8af80ec6a5300ad7a28 /datapath
parentd2cd45db48e2713b74c3a31f746f923a72294e46 (diff)
parent6dd3fad481b5d801695c2b0529c7d37cac2c9b19 (diff)
Merge citrix into master.
This was a somewhat difficult merge since there was a fair amount of superficially divergent development on the two branches, especially in the datapath. This has been build-tested against XenServer 5.5.0 and XenServer 5.7.0 build 15122. It has been booted and connected to XenCenter on 5.5.0. The merge revealed a couple of outstanding bugs, which will be fixed on citrix and then merged back into master.
Diffstat (limited to 'datapath')
-rw-r--r--datapath/actions.c6
-rw-r--r--datapath/datapath.c113
-rw-r--r--datapath/datapath.h3
-rw-r--r--datapath/dp_dev.c2
-rw-r--r--datapath/dp_sysfs.h11
-rw-r--r--datapath/dp_sysfs_dp.c142
-rw-r--r--datapath/dp_sysfs_if.c22
-rw-r--r--datapath/linux-2.6/compat-2.6/include/linux/kobject.h14
-rw-r--r--datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h12
9 files changed, 150 insertions, 175 deletions
diff --git a/datapath/actions.c b/datapath/actions.c
index a037e432..8a3e8abb 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -96,7 +96,7 @@ modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
* when we send the packet out on the wire, and it will fail at
* that point because skb_checksum_setup() will not look inside
* an 802.1Q header. */
- skb_checksum_setup(skb);
+ vswitch_skb_checksum_setup(skb);
/* GSO is not implemented for packets with an 802.1Q header, so
* we have to do segmentation before we add that header.
@@ -361,7 +361,7 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
* then freeing the original skbuff is wasteful. So the following code
* is slightly obscure just to avoid that. */
int prev_port = -1;
- int err = 0;
+ int err;
for (; n_actions > 0; a++, n_actions--) {
WARN_ON_ONCE(skb_shared(skb));
if (prev_port != -1) {
@@ -420,5 +420,5 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
do_output(dp, skb, prev_port);
else
kfree_skb(skb);
- return err;
+ return 0;
}
diff --git a/datapath/datapath.c b/datapath/datapath.c
index bf8043b6..de607e8b 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -165,7 +165,8 @@ static void dp_ifinfo_notify(int event, struct net_bridge_port *port)
kfree_skb(skb);
goto errout;
}
- err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
+ return;
errout:
if (err < 0)
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
@@ -224,9 +225,7 @@ static int create_dp(int dp_idx, const char __user *devnamep)
/* Initialize kobject for bridge. This will be added as
* /sys/class/net/<devname>/bridge later, if sysfs is enabled. */
- kobject_set_name(&dp->ifobj, SYSFS_BRIDGE_PORT_SUBDIR); /* "bridge" */
dp->ifobj.kset = NULL;
- dp->ifobj.parent = NULL;
kobject_init(&dp->ifobj, &dp_ktype);
/* Allocate table. */
@@ -256,9 +255,7 @@ static int create_dp(int dp_idx, const char __user *devnamep)
mutex_unlock(&dp_mutex);
rtnl_unlock();
-#ifdef SUPPORT_SYSFS
dp_sysfs_add_dp(dp);
-#endif
return 0;
@@ -286,9 +283,7 @@ static void do_destroy_dp(struct datapath *dp)
if (p->port_no != ODPP_LOCAL)
dp_del_port(p);
-#ifdef SUPPORT_SYSFS
dp_sysfs_del_dp(dp);
-#endif
rcu_assign_pointer(dps[dp->dp_idx], NULL);
@@ -333,7 +328,7 @@ static void release_nbp(struct kobject *kobj)
}
struct kobj_type brport_ktype = {
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
.sysfs_ops = &brport_sysfs_ops,
#endif
.release = release_nbp
@@ -370,9 +365,7 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no)
/* Initialize kobject for bridge. This will be added as
* /sys/class/net/<devname>/brport later, if sysfs is enabled. */
- kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); /* "brport" */
p->kobj.kset = NULL;
- p->kobj.parent = &p->dev->NETDEV_DEV_MEMBER.kobj;
kobject_init(&p->kobj, &brport_ktype);
dp_ifinfo_notify(RTM_NEWLINK, p);
@@ -392,11 +385,6 @@ static int add_port(int dp_idx, struct odp_port __user *portp)
if (copy_from_user(&port, portp, sizeof port))
goto out;
port.devname[IFNAMSIZ - 1] = '\0';
- port_no = port.port;
-
- err = -EINVAL;
- if (port_no < 0 || port_no >= DP_MAX_PORTS)
- goto out;
rtnl_lock();
dp = get_dp_locked(dp_idx);
@@ -404,10 +392,13 @@ static int add_port(int dp_idx, struct odp_port __user *portp)
if (!dp)
goto out_unlock_rtnl;
- err = -EEXIST;
- if (dp->ports[port_no])
- goto out_unlock_dp;
+ for (port_no = 1; port_no < DP_MAX_PORTS; port_no++)
+ if (!dp->ports[port_no])
+ goto got_port_no;
+ err = -EXFULL;
+ goto out_unlock_dp;
+got_port_no:
if (!(port.flags & ODP_PORT_INTERNAL)) {
err = -ENODEV;
dev = dev_get_by_name(&init_net, port.devname);
@@ -430,9 +421,9 @@ static int add_port(int dp_idx, struct odp_port __user *portp)
if (err)
goto out_put;
-#ifdef SUPPORT_SYSFS
dp_sysfs_add_if(dp->ports[port_no]);
-#endif
+
+ err = __put_user(port_no, &port.port);
out_put:
dev_put(dev);
@@ -448,10 +439,8 @@ int dp_del_port(struct net_bridge_port *p)
{
ASSERT_RTNL();
-#ifdef SUPPORT_SYSFS
if (p->port_no != ODPP_LOCAL)
dp_sysfs_del_if(p);
-#endif
dp_ifinfo_notify(RTM_DELLINK, p);
p->dp->n_ports--;
@@ -587,7 +576,7 @@ static int dp_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
#error
#endif
-#ifdef CONFIG_XEN
+#if defined(CONFIG_XEN) && LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
/* This code is copied verbatim from net/dev/core.c in Xen's
* linux-2.6.18-92.1.10.el5.xs5.0.0.394.644. We can't call those functions
* directly because they aren't exported. */
@@ -603,7 +592,7 @@ static int skb_pull_up_to(struct sk_buff *skb, void *ptr)
}
}
-int skb_checksum_setup(struct sk_buff *skb)
+int vswitch_skb_checksum_setup(struct sk_buff *skb)
{
if (skb->proto_csum_blank) {
if (skb->protocol != htons(ETH_P_IP))
@@ -634,7 +623,9 @@ int skb_checksum_setup(struct sk_buff *skb)
out:
return -EPROTO;
}
-#endif
+#else
+int vswitch_skb_checksum_setup(struct sk_buff *skb) { return 0; }
+#endif /* CONFIG_XEN && linux == 2.6.18 */
int
dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
@@ -660,7 +651,7 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
* the non-Xen case, but it is difficult to trigger or test this case
* there, hence the WARN_ON_ONCE().
*/
- err = skb_checksum_setup(skb);
+ err = vswitch_skb_checksum_setup(skb);
if (err)
goto err_kfree_skb;
#ifndef CHECKSUM_HW
@@ -836,6 +827,7 @@ static void get_stats(struct sw_flow *flow, struct odp_flow_stats *stats)
stats->n_bytes = flow->byte_count;
stats->ip_tos = flow->ip_tos;
stats->tcp_flags = flow->tcp_flags;
+ stats->error = 0;
}
static void clear_stats(struct sw_flow *flow)
@@ -964,8 +956,6 @@ static int put_actions(const struct sw_flow *flow, struct odp_flow __user *ufp)
if (!n_actions)
return 0;
- if (ufp->n_actions > INT_MAX / sizeof(union odp_action))
- return -EINVAL;
sf_acts = rcu_dereference(flow->sf_acts);
if (__put_user(sf_acts->n_actions, &ufp->n_actions) ||
@@ -991,9 +981,7 @@ static int answer_query(struct sw_flow *flow, struct odp_flow __user *ufp)
return put_actions(flow, ufp);
}
-static int del_or_query_flow(struct datapath *dp,
- struct odp_flow __user *ufp,
- unsigned int cmd)
+static int del_flow(struct datapath *dp, struct odp_flow __user *ufp)
{
struct dp_table *table = rcu_dereference(dp->table);
struct odp_flow uf;
@@ -1010,29 +998,24 @@ static int del_or_query_flow(struct datapath *dp,
if (!flow)
goto error;
- if (cmd == ODP_FLOW_DEL) {
- /* XXX redundant lookup */
- error = dp_table_delete(table, flow);
- if (error)
- goto error;
+ /* XXX redundant lookup */
+ error = dp_table_delete(table, flow);
+ if (error)
+ goto error;
- /* XXX These statistics might lose a few packets, since other
- * CPUs can be using this flow. We used to synchronize_rcu()
- * to make sure that we get completely accurate stats, but that
- * blows our performance, badly. */
- dp->n_flows--;
- error = answer_query(flow, ufp);
- flow_deferred_free(flow);
- } else {
- error = answer_query(flow, ufp);
- }
+ /* XXX These statistics might lose a few packets, since other CPUs can
+ * be using this flow. We used to synchronize_rcu() to make sure that
+ * we get completely accurate stats, but that blows our performance,
+ * badly. */
+ dp->n_flows--;
+ error = answer_query(flow, ufp);
+ flow_deferred_free(flow);
error:
return error;
}
-static int query_multiple_flows(struct datapath *dp,
- const struct odp_flowvec *flowvec)
+static int query_flows(struct datapath *dp, const struct odp_flowvec *flowvec)
{
struct dp_table *table = rcu_dereference(dp->table);
int i;
@@ -1048,7 +1031,7 @@ static int query_multiple_flows(struct datapath *dp,
flow = dp_table_lookup(table, &uf.key);
if (!flow)
- error = __clear_user(&ufp->stats, sizeof ufp->stats);
+ error = __put_user(ENOENT, &ufp->stats.error);
else
error = answer_query(flow, ufp);
if (error)
@@ -1181,8 +1164,7 @@ error:
return err;
}
-static int
-get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
+static int get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp)
{
struct odp_stats stats;
int i;
@@ -1297,7 +1279,7 @@ list_ports(struct datapath *dp, struct odp_portvec __user *pvp)
break;
}
}
- return put_user(idx, &pvp->n_ports);
+ return put_user(dp->n_ports, &pvp->n_ports);
}
/* RCU callback for freeing a dp_port_group */
@@ -1381,24 +1363,28 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
/* Handle commands with special locking requirements up front. */
switch (cmd) {
case ODP_DP_CREATE:
- return create_dp(dp_idx, (char __user *)argp);
+ err = create_dp(dp_idx, (char __user *)argp);
+ goto exit;
case ODP_DP_DESTROY:
- return destroy_dp(dp_idx);
+ err = destroy_dp(dp_idx);
+ goto exit;
case ODP_PORT_ADD:
- return add_port(dp_idx, (struct odp_port __user *)argp);
+ err = add_port(dp_idx, (struct odp_port __user *)argp);
+ goto exit;
case ODP_PORT_DEL:
err = get_user(port_no, (int __user *)argp);
- if (err)
- break;
- return del_port(dp_idx, port_no);
+ if (!err)
+ err = del_port(dp_idx, port_no);
+ goto exit;
}
dp = get_dp_locked(dp_idx);
+ err = -ENODEV;
if (!dp)
- return -ENODEV;
+ goto exit;
switch (cmd) {
case ODP_DP_STATS:
@@ -1460,13 +1446,11 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
break;
case ODP_FLOW_DEL:
- case ODP_FLOW_GET:
- err = del_or_query_flow(dp, (struct odp_flow __user *)argp,
- cmd);
+ err = del_flow(dp, (struct odp_flow __user *)argp);
break;
- case ODP_FLOW_GET_MULTIPLE:
- err = do_flowvec_ioctl(dp, argp, query_multiple_flows);
+ case ODP_FLOW_GET:
+ err = do_flowvec_ioctl(dp, argp, query_flows);
break;
case ODP_FLOW_LIST:
@@ -1482,6 +1466,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
break;
}
mutex_unlock(&dp->mutex);
+exit:
return err;
}
diff --git a/datapath/datapath.h b/datapath/datapath.h
index 62c79d43..b5200848 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -18,6 +18,7 @@
#include <linux/netdevice.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
+#include <linux/version.h>
#include "flow.h"
#include "dp_sysfs.h"
@@ -133,4 +134,6 @@ static inline int skb_checksum_setup(struct sk_buff *skb)
}
#endif
+int vswitch_skb_checksum_setup(struct sk_buff *skb);
+
#endif /* datapath.h */
diff --git a/datapath/dp_dev.c b/datapath/dp_dev.c
index d11e7f6f..069127e0 100644
--- a/datapath/dp_dev.c
+++ b/datapath/dp_dev.c
@@ -118,7 +118,7 @@ static void dp_getinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
{
struct dp_dev *dp_dev = dp_dev_priv(netdev);
strcpy(info->driver, "openvswitch");
- sprintf(info->bus_info, "%d", dp_dev->dp->dp_idx);
+ sprintf(info->bus_info, "%d.%d", dp_dev->dp->dp_idx, dp_dev->port_no);
}
static struct ethtool_ops dp_ethtool_ops = {
diff --git a/datapath/dp_sysfs.h b/datapath/dp_sysfs.h
index c0ac01b9..be044eaf 100644
--- a/datapath/dp_sysfs.h
+++ b/datapath/dp_sysfs.h
@@ -20,16 +20,7 @@ int dp_sysfs_del_dp(struct datapath *dp);
int dp_sysfs_add_if(struct net_bridge_port *p);
int dp_sysfs_del_if(struct net_bridge_port *p);
-#include <linux/version.h>
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
-#define SUPPORT_SYSFS 1
-#else
-/* We only support sysfs on Linux 2.6.18 because that's the only place we
- * really need it (on Xen, for brcompat) and it's a big pain to try to support
- * multiple versions. */
-#endif
-
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
extern struct sysfs_ops brport_sysfs_ops;
#endif
diff --git a/datapath/dp_sysfs_dp.c b/datapath/dp_sysfs_dp.c
index 9699a076..fafd9a9c 100644
--- a/datapath/dp_sysfs_dp.c
+++ b/datapath/dp_sysfs_dp.c
@@ -28,22 +28,26 @@
#include "datapath.h"
#include "dp_dev.h"
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
#define to_dev(obj) container_of(obj, struct device, kobj)
/* Hack to attempt to build on more platforms. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
-#define to_kobj(d) &(d)->class_dev.kobj
#define DP_DEVICE_ATTR CLASS_DEVICE_ATTR
+#define DEVICE_PARAMS struct class_device *d
+#define DEVICE_ARGS d
+#define DEV_ATTR(NAME) class_device_attr_##NAME
#else
-#define to_kobj(d) &(d)->dev.kobj
#define DP_DEVICE_ATTR DEVICE_ATTR
+#define DEVICE_PARAMS struct device *d, struct device_attribute *attr
+#define DEVICE_ARGS d, attr
+#define DEV_ATTR(NAME) dev_attr_##NAME
#endif
/*
* Common code for storing bridge parameters.
*/
-static ssize_t store_bridge_parm(struct class_device *d,
+static ssize_t store_bridge_parm(DEVICE_PARAMS,
const char *buf, size_t len,
void (*set)(struct datapath *, unsigned long))
{
@@ -76,8 +80,7 @@ static ssize_t store_bridge_parm(struct class_device *d,
}
-static ssize_t show_forward_delay(struct class_device *d,
- char *buf)
+static ssize_t show_forward_delay(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -99,15 +102,15 @@ static void set_forward_delay(struct datapath *dp, unsigned long val)
#endif
}
-static ssize_t store_forward_delay(struct class_device *d,
+static ssize_t store_forward_delay(DEVICE_PARAMS,
const char *buf, size_t len)
{
- return store_bridge_parm(d, buf, len, set_forward_delay);
+ return store_bridge_parm(DEVICE_ARGS, buf, len, set_forward_delay);
}
static DP_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
show_forward_delay, store_forward_delay);
-static ssize_t show_hello_time(struct class_device *d, char *buf)
+static ssize_t show_hello_time(DEVICE_PARAMS, char *buf)
{
#if 0
return sprintf(buf, "%lu\n",
@@ -129,17 +132,16 @@ static void set_hello_time(struct datapath *dp, unsigned long val)
#endif
}
-static ssize_t store_hello_time(struct class_device *d,
+static ssize_t store_hello_time(DEVICE_PARAMS,
const char *buf,
size_t len)
{
- return store_bridge_parm(d, buf, len, set_hello_time);
+ return store_bridge_parm(DEVICE_ARGS, buf, len, set_hello_time);
}
static DP_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
store_hello_time);
-static ssize_t show_max_age(struct class_device *d,
- char *buf)
+static ssize_t show_max_age(DEVICE_PARAMS, char *buf)
{
#if 0
return sprintf(buf, "%lu\n",
@@ -161,15 +163,14 @@ static void set_max_age(struct datapath *dp, unsigned long val)
#endif
}
-static ssize_t store_max_age(struct class_device *d,
+static ssize_t store_max_age(DEVICE_PARAMS,
const char *buf, size_t len)
{
- return store_bridge_parm(d, buf, len, set_max_age);
+ return store_bridge_parm(DEVICE_ARGS, buf, len, set_max_age);
}
static DP_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
-static ssize_t show_ageing_time(struct class_device *d,
- char *buf)
+static ssize_t show_ageing_time(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -188,16 +189,15 @@ static void set_ageing_time(struct datapath *dp, unsigned long val)
#endif
}
-static ssize_t store_ageing_time(struct class_device *d,
+static ssize_t store_ageing_time(DEVICE_PARAMS,
const char *buf, size_t len)
{
- return store_bridge_parm(d, buf, len, set_ageing_time);
+ return store_bridge_parm(DEVICE_ARGS, buf, len, set_ageing_time);
}
static DP_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
store_ageing_time);
-static ssize_t show_stp_state(struct class_device *d,
- char *buf)
+static ssize_t show_stp_state(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -208,7 +208,7 @@ static ssize_t show_stp_state(struct class_device *d,
}
-static ssize_t store_stp_state(struct class_device *d,
+static ssize_t store_stp_state(DEVICE_PARAMS,
const char *buf,
size_t len)
{
@@ -236,8 +236,7 @@ static ssize_t store_stp_state(struct class_device *d,
static DP_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
store_stp_state);
-static ssize_t show_priority(struct class_device *d,
- char *buf)
+static ssize_t show_priority(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -257,15 +256,14 @@ static void set_priority(struct datapath *dp, unsigned long val)
#endif
}
-static ssize_t store_priority(struct class_device *d,
+static ssize_t store_priority(DEVICE_PARAMS,
const char *buf, size_t len)
{
- return store_bridge_parm(d, buf, len, set_priority);
+ return store_bridge_parm(DEVICE_ARGS, buf, len, set_priority);
}
static DP_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
-static ssize_t show_root_id(struct class_device *d,
- char *buf)
+static ssize_t show_root_id(DEVICE_PARAMS, char *buf)
{
#if 0
return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
@@ -275,8 +273,7 @@ static ssize_t show_root_id(struct class_device *d,
}
static DP_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
-static ssize_t show_bridge_id(struct class_device *d,
- char *buf)
+static ssize_t show_bridge_id(DEVICE_PARAMS, char *buf)
{
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
const unsigned char *addr = dp->ports[ODPP_LOCAL]->dev->dev_addr;
@@ -287,8 +284,7 @@ static ssize_t show_bridge_id(struct class_device *d,
}
static DP_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
-static ssize_t show_root_port(struct class_device *d,
- char *buf)
+static ssize_t show_root_port(DEVICE_PARAMS, char *buf)
{
#if 0
return sprintf(buf, "%d\n", to_bridge(d)->root_port);
@@ -298,8 +294,7 @@ static ssize_t show_root_port(struct class_device *d,
}
static DP_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
-static ssize_t show_root_path_cost(struct class_device *d,
- char *buf)
+static ssize_t show_root_path_cost(DEVICE_PARAMS, char *buf)
{
#if 0
return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
@@ -309,8 +304,7 @@ static ssize_t show_root_path_cost(struct class_device *d,
}
static DP_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
-static ssize_t show_topology_change(struct class_device *d,
- char *buf)
+static ssize_t show_topology_change(DEVICE_PARAMS, char *buf)
{
#if 0
return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
@@ -320,8 +314,7 @@ static ssize_t show_topology_change(struct class_device *d,
}
static DP_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
-static ssize_t show_topology_change_detected(struct class_device *d,
- char *buf)
+static ssize_t show_topology_change_detected(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -333,8 +326,7 @@ static ssize_t show_topology_change_detected(struct class_device *d,
static DP_DEVICE_ATTR(topology_change_detected, S_IRUGO,
show_topology_change_detected, NULL);
-static ssize_t show_hello_timer(struct class_device *d,
- char *buf)
+static ssize_t show_hello_timer(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -345,8 +337,7 @@ static ssize_t show_hello_timer(struct class_device *d,
}
static DP_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
-static ssize_t show_tcn_timer(struct class_device *d,
- char *buf)
+static ssize_t show_tcn_timer(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -357,8 +348,7 @@ static ssize_t show_tcn_timer(struct class_device *d,
}
static DP_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
-static ssize_t show_topology_change_timer(struct class_device *d,
- char *buf)
+static ssize_t show_topology_change_timer(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -370,8 +360,7 @@ static ssize_t show_topology_change_timer(struct class_device *d,
static DP_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
NULL);
-static ssize_t show_gc_timer(struct class_device *d,
- char *buf)
+static ssize_t show_gc_timer(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -382,8 +371,7 @@ static ssize_t show_gc_timer(struct class_device *d,
}
static DP_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
-static ssize_t show_group_addr(struct class_device *d,
- char *buf)
+static ssize_t show_group_addr(DEVICE_PARAMS, char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -396,7 +384,7 @@ static ssize_t show_group_addr(struct class_device *d,
#endif
}
-static ssize_t store_group_addr(struct class_device *d,
+static ssize_t store_group_addr(DEVICE_PARAMS,
const char *buf, size_t len)
{
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
@@ -439,23 +427,23 @@ static DP_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
show_group_addr, store_group_addr);
static struct attribute *bridge_attrs[] = {
- &class_device_attr_forward_delay.attr,
- &class_device_attr_hello_time.attr,
- &class_device_attr_max_age.attr,
- &class_device_attr_ageing_time.attr,
- &class_device_attr_stp_state.attr,
- &class_device_attr_priority.attr,
- &class_device_attr_bridge_id.attr,
- &class_device_attr_root_id.attr,
- &class_device_attr_root_path_cost.attr,
- &class_device_attr_root_port.attr,
- &class_device_attr_topology_change.attr,
- &class_device_attr_topology_change_detected.attr,
- &class_device_attr_hello_timer.attr,
- &class_device_attr_tcn_timer.attr,
- &class_device_attr_topology_change_timer.attr,
- &class_device_attr_gc_timer.attr,
- &class_device_attr_group_addr.attr,
+ &DEV_ATTR(forward_delay).attr,
+ &DEV_ATTR(hello_time).attr,
+ &DEV_ATTR(max_age).attr,
+ &DEV_ATTR(ageing_time).attr,
+ &DEV_ATTR(stp_state).attr,
+ &DEV_ATTR(priority).attr,
+ &DEV_ATTR(bridge_id).attr,
+ &DEV_ATTR(root_id).attr,
+ &DEV_ATTR(root_path_cost).attr,
+ &DEV_ATTR(root_port).attr,
+ &DEV_ATTR(topology_change).attr,
+ &DEV_ATTR(topology_change_detected).attr,
+ &DEV_ATTR(hello_timer).attr,
+ &DEV_ATTR(tcn_timer).attr,
+ &DEV_ATTR(topology_change_timer).attr,
+ &DEV_ATTR(gc_timer).attr,
+ &DEV_ATTR(group_addr).attr,
NULL
};
@@ -476,7 +464,7 @@ static struct attribute_group bridge_group = {
*/
int dp_sysfs_add_dp(struct datapath *dp)
{
- struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
+ struct kobject *kobj = &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj;
int err;
err = sysfs_create_group(kobj, &bridge_group);
@@ -486,12 +474,11 @@ int dp_sysfs_add_dp(struct datapath *dp)
goto out1;
}
- /* Create /sys/class/net/<devname>/bridge directory. */
- dp->ifobj.parent = kobj;
- err = kobject_add(&dp->ifobj);
+ /* Create /sys/class/net/<devname>/brif directory. */
+ err = kobject_add(&dp->ifobj, kobj, SYSFS_BRIDGE_PORT_SUBDIR);
if (err) {
pr_info("%s: can't add kobject (directory) %s/%s\n",
- __FUNCTION__, dp_name(dp), dp->ifobj.name);
+ __FUNCTION__, dp_name(dp), kobject_name(&dp->ifobj));
goto out2;
}
kobject_uevent(&dp->ifobj, KOBJ_ADD);
@@ -505,21 +492,16 @@ int dp_sysfs_add_dp(struct datapath *dp)
int dp_sysfs_del_dp(struct datapath *dp)
{
- struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
+ struct kobject *kobj = &dp->ports[ODPP_LOCAL]->dev->NETDEV_DEV_MEMBER.kobj;
kobject_del(&dp->ifobj);
sysfs_remove_group(kobj, &bridge_group);
return 0;
}
-#else /* !SUPPORT_SYSFS */
+#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 net_bridge_port *p) { return 0; }
-int dp_sysfs_del_if(struct net_bridge_port *p)
-{
- dev_put(p->dev);
- kfree(p);
- return 0;
-}
-#endif /* !SUPPORT_SYSFS */
+int dp_sysfs_del_if(struct net_bridge_port *p) { return 0; }
+#endif /* !CONFIG_SYSFS */
diff --git a/datapath/dp_sysfs_if.c b/datapath/dp_sysfs_if.c
index ab928f6c..95c26dc4 100644
--- a/datapath/dp_sysfs_if.c
+++ b/datapath/dp_sysfs_if.c
@@ -21,7 +21,7 @@
#include "dp_sysfs.h"
#include "datapath.h"
-#ifdef SUPPORT_SYSFS
+#ifdef CONFIG_SYSFS
struct brport_attribute {
struct attribute attr;
@@ -278,9 +278,10 @@ int dp_sysfs_add_if(struct net_bridge_port *p)
int err;
/* Create /sys/class/net/<devname>/brport directory. */
- err = kobject_add(&p->kobj);
+ err = kobject_add(&p->kobj, &p->dev->NETDEV_DEV_MEMBER.kobj,
+ SYSFS_BRIDGE_PORT_ATTR);
if (err)
- goto err_put;
+ goto err;
/* Create symlink from /sys/class/net/<devname>/brport/bridge to
* /sys/class/net/<bridgename>. */
@@ -306,15 +307,12 @@ int dp_sysfs_add_if(struct net_bridge_port *p)
kobject_uevent(&p->kobj, KOBJ_ADD);
- return err;
+ return 0;
err_del:
kobject_del(&p->kobj);
-err_put:
- kobject_put(&p->kobj);
-
- /* Ensure that dp_sysfs_del_if becomes a no-op. */
- p->kobj.dentry = NULL;
+err:
+ p->linkname[0] = 0;
return err;
}
@@ -322,12 +320,10 @@ int dp_sysfs_del_if(struct net_bridge_port *p)
{
if (p->linkname[0]) {
sysfs_remove_link(&p->dp->ifobj, p->linkname);
- p->linkname[0] = '\0';
- }
- if (p->kobj.dentry) {
kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
+ p->linkname[0] = '\0';
}
return 0;
}
-#endif /* SUPPORT_SYSFS */
+#endif /* CONFIG_SYSFS */
diff --git a/datapath/linux-2.6/compat-2.6/include/linux/kobject.h b/datapath/linux-2.6/compat-2.6/include/linux/kobject.h
index c0de3d2e..4cf797e3 100644
--- a/datapath/linux-2.6/compat-2.6/include/linux/kobject.h
+++ b/datapath/linux-2.6/compat-2.6/include/linux/kobject.h
@@ -4,6 +4,7 @@
#include_next <linux/kobject.h>
#include <linux/version.h>
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
#define kobject_init(kobj, ktype) rpl_kobject_init(kobj, ktype)
static inline void rpl_kobject_init(struct kobject *kobj, struct kobj_type *ktype)
@@ -11,6 +12,19 @@ static inline void rpl_kobject_init(struct kobject *kobj, struct kobj_type *ktyp
kobj->ktype = ktype;
(kobject_init)(kobj);
}
+
+#define kobject_add(kobj, parent, name) rpl_kobject_add(kobj, parent, name)
+static inline int rpl_kobject_add(struct kobject *kobj,
+ struct kobject *parent,
+ const char *name)
+{
+ int err = kobject_set_name(kobj, "%s", name);
+ if (err)
+ return err;
+ kobj->parent = parent;
+ return (kobject_add)(kobj);
+}
#endif
+
#endif /* linux/kobject.h wrapper */
diff --git a/datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h b/datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h
index 8bc51560..4d7bd784 100644
--- a/datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h
+++ b/datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h
@@ -4,7 +4,7 @@
#include_next <linux/rtnetlink.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
-static inline int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
+static inline void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
u32 group, struct nlmsghdr *nlh, gfp_t flags)
{
BUG_ON(nlh); /* not implemented */
@@ -12,7 +12,6 @@ static inline int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
/* errors reported via destination sk->sk_err */
nlmsg_multicast(rtnl, skb, 0, group);
}
- return 0;
}
static inline void rtnl_set_sk_err(struct net *net, u32 group, int error)
@@ -20,10 +19,15 @@ static inline void rtnl_set_sk_err(struct net *net, u32 group, int error)
netlink_set_err(rtnl, 0, group, error);
}
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+/* No 'net' parameter in these versions. */
#define rtnl_notify(skb, net, pid, group, nlh, flags) \
- ((void) (net), rtnl_notify(skb, pid, group, nlh, flags))
+ ((void) (net), (void) rtnl_notify(skb, pid, group, nlh, flags))
#define rtnl_set_sk_err(net, group, error) \
((void) (net), rtnl_set_sk_err(group, error))
-#endif /* linux kernel < 2.6.25 */
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+/* Make the return type effectively 'void' to match Linux 2.6.30+. */
+#define rtnl_notify(skb, net, pid, group, nlh, flags) \
+ ((void) rtnl_notify(skb, net, pid, group, nlh, flags))
+#endif
#endif /* linux/rtnetlink.h wrapper */