diff options
author | Ben Pfaff <blp@nicira.com> | 2009-08-19 13:03:46 -0700 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2009-08-19 13:03:46 -0700 |
commit | 8fef8c7121222233075a03d57db7e0b48d5f6be5 (patch) | |
tree | 5cb9822a490c41694be2c8af80ec6a5300ad7a28 /datapath | |
parent | d2cd45db48e2713b74c3a31f746f923a72294e46 (diff) | |
parent | 6dd3fad481b5d801695c2b0529c7d37cac2c9b19 (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.c | 6 | ||||
-rw-r--r-- | datapath/datapath.c | 113 | ||||
-rw-r--r-- | datapath/datapath.h | 3 | ||||
-rw-r--r-- | datapath/dp_dev.c | 2 | ||||
-rw-r--r-- | datapath/dp_sysfs.h | 11 | ||||
-rw-r--r-- | datapath/dp_sysfs_dp.c | 142 | ||||
-rw-r--r-- | datapath/dp_sysfs_if.c | 22 | ||||
-rw-r--r-- | datapath/linux-2.6/compat-2.6/include/linux/kobject.h | 14 | ||||
-rw-r--r-- | datapath/linux-2.6/compat-2.6/include/linux/rtnetlink.h | 12 |
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 */ |