Commit edb5e46fc03d0a45f2b41e3717631f7af7e9fc19
Committed by
David S. Miller
1 parent
0e5eabac49
Exists in
master
and in
7 other branches
[BRIDGE]: limited ethtool support
Add limited ethtool support to bridge to allow disabling features. Note: if underlying device does not support a feature (like checksum offload), then the bridge device won't inherit it. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 3 changed files with 67 additions and 3 deletions Side-by-side Diff
net/bridge/br_device.c
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | #include <linux/kernel.h> |
17 | 17 | #include <linux/netdevice.h> |
18 | 18 | #include <linux/etherdevice.h> |
19 | +#include <linux/ethtool.h> | |
19 | 20 | |
20 | 21 | #include <asm/uaccess.h> |
21 | 22 | #include "br_private.h" |
... | ... | @@ -106,6 +107,64 @@ |
106 | 107 | return err; |
107 | 108 | } |
108 | 109 | |
110 | +static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |
111 | +{ | |
112 | + strcpy(info->driver, "bridge"); | |
113 | + strcpy(info->version, BR_VERSION); | |
114 | + strcpy(info->fw_version, "N/A"); | |
115 | + strcpy(info->bus_info, "N/A"); | |
116 | +} | |
117 | + | |
118 | +static int br_set_sg(struct net_device *dev, u32 data) | |
119 | +{ | |
120 | + struct net_bridge *br = netdev_priv(dev); | |
121 | + | |
122 | + if (data) | |
123 | + br->feature_mask |= NETIF_F_SG; | |
124 | + else | |
125 | + br->feature_mask &= ~NETIF_F_SG; | |
126 | + | |
127 | + br_features_recompute(br); | |
128 | + return 0; | |
129 | +} | |
130 | + | |
131 | +static int br_set_tso(struct net_device *dev, u32 data) | |
132 | +{ | |
133 | + struct net_bridge *br = netdev_priv(dev); | |
134 | + | |
135 | + if (data) | |
136 | + br->feature_mask |= NETIF_F_TSO; | |
137 | + else | |
138 | + br->feature_mask &= ~NETIF_F_TSO; | |
139 | + | |
140 | + br_features_recompute(br); | |
141 | + return 0; | |
142 | +} | |
143 | + | |
144 | +static int br_set_tx_csum(struct net_device *dev, u32 data) | |
145 | +{ | |
146 | + struct net_bridge *br = netdev_priv(dev); | |
147 | + | |
148 | + if (data) | |
149 | + br->feature_mask |= NETIF_F_IP_CSUM; | |
150 | + else | |
151 | + br->feature_mask &= ~NETIF_F_IP_CSUM; | |
152 | + | |
153 | + br_features_recompute(br); | |
154 | + return 0; | |
155 | +} | |
156 | + | |
157 | +static struct ethtool_ops br_ethtool_ops = { | |
158 | + .get_drvinfo = br_getinfo, | |
159 | + .get_link = ethtool_op_get_link, | |
160 | + .get_sg = ethtool_op_get_sg, | |
161 | + .set_sg = br_set_sg, | |
162 | + .get_tx_csum = ethtool_op_get_tx_csum, | |
163 | + .set_tx_csum = br_set_tx_csum, | |
164 | + .get_tso = ethtool_op_get_tso, | |
165 | + .set_tso = br_set_tso, | |
166 | +}; | |
167 | + | |
109 | 168 | void br_dev_setup(struct net_device *dev) |
110 | 169 | { |
111 | 170 | memset(dev->dev_addr, 0, ETH_ALEN); |
112 | 171 | |
... | ... | @@ -120,9 +179,13 @@ |
120 | 179 | dev->change_mtu = br_change_mtu; |
121 | 180 | dev->destructor = free_netdev; |
122 | 181 | SET_MODULE_OWNER(dev); |
182 | + SET_ETHTOOL_OPS(dev, &br_ethtool_ops); | |
123 | 183 | dev->stop = br_dev_stop; |
124 | 184 | dev->tx_queue_len = 0; |
125 | 185 | dev->set_mac_address = br_set_mac_address; |
126 | 186 | dev->priv_flags = IFF_EBRIDGE; |
187 | + | |
188 | + dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | |
189 | + | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM; | |
127 | 190 | } |
net/bridge/br_if.c
... | ... | @@ -182,6 +182,7 @@ |
182 | 182 | br->bridge_id.prio[1] = 0x00; |
183 | 183 | memset(br->bridge_id.addr, 0, ETH_ALEN); |
184 | 184 | |
185 | + br->feature_mask = dev->features; | |
185 | 186 | br->stp_enabled = 0; |
186 | 187 | br->designated_root = br->bridge_id; |
187 | 188 | br->root_path_cost = 0; |
... | ... | @@ -349,9 +350,8 @@ |
349 | 350 | struct net_bridge_port *p; |
350 | 351 | unsigned long features, checksum; |
351 | 352 | |
352 | - features = NETIF_F_SG | NETIF_F_FRAGLIST | |
353 | - | NETIF_F_HIGHDMA | NETIF_F_TSO; | |
354 | - checksum = NETIF_F_IP_CSUM; /* least commmon subset */ | |
353 | + features = br->feature_mask &~ NETIF_F_IP_CSUM; | |
354 | + checksum = br->feature_mask & NETIF_F_IP_CSUM; | |
355 | 355 | |
356 | 356 | list_for_each_entry(p, &br->port_list, list) { |
357 | 357 | if (!(p->dev->features |