diff options
author | Santwona Behera <santwona.behera@sun.com> | 2009-02-20 03:58:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-20 03:58:13 -0500 |
commit | 59089d8d162ddcb5c434672e915331964d38a754 (patch) | |
tree | 2d2595beffc410caa8054922976206fb600f8750 /net/core | |
parent | 3876732c12cd2b9896e8c3e86fad142112e93569 (diff) |
ethtool: Add RX pkt classification interface
Signed-off-by: Santwona Behera <santwona.behera@sun.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/ethtool.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 947710a36ced..244ca56dffac 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -209,34 +209,62 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | |||
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int ethtool_set_rxhash(struct net_device *dev, void __user *useraddr) | 212 | static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) |
213 | { | 213 | { |
214 | struct ethtool_rxnfc cmd; | 214 | struct ethtool_rxnfc cmd; |
215 | 215 | ||
216 | if (!dev->ethtool_ops->set_rxhash) | 216 | if (!dev->ethtool_ops->set_rxnfc) |
217 | return -EOPNOTSUPP; | 217 | return -EOPNOTSUPP; |
218 | 218 | ||
219 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | 219 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) |
220 | return -EFAULT; | 220 | return -EFAULT; |
221 | 221 | ||
222 | return dev->ethtool_ops->set_rxhash(dev, &cmd); | 222 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); |
223 | } | 223 | } |
224 | 224 | ||
225 | static int ethtool_get_rxhash(struct net_device *dev, void __user *useraddr) | 225 | static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) |
226 | { | 226 | { |
227 | struct ethtool_rxnfc info; | 227 | struct ethtool_rxnfc info; |
228 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
229 | int ret; | ||
230 | void *rule_buf = NULL; | ||
228 | 231 | ||
229 | if (!dev->ethtool_ops->get_rxhash) | 232 | if (!ops->get_rxnfc) |
230 | return -EOPNOTSUPP; | 233 | return -EOPNOTSUPP; |
231 | 234 | ||
232 | if (copy_from_user(&info, useraddr, sizeof(info))) | 235 | if (copy_from_user(&info, useraddr, sizeof(info))) |
233 | return -EFAULT; | 236 | return -EFAULT; |
234 | 237 | ||
235 | dev->ethtool_ops->get_rxhash(dev, &info); | 238 | if (info.cmd == ETHTOOL_GRXCLSRLALL) { |
239 | if (info.rule_cnt > 0) { | ||
240 | rule_buf = kmalloc(info.rule_cnt * sizeof(u32), | ||
241 | GFP_USER); | ||
242 | if (!rule_buf) | ||
243 | return -ENOMEM; | ||
244 | } | ||
245 | } | ||
236 | 246 | ||
247 | ret = ops->get_rxnfc(dev, &info, rule_buf); | ||
248 | if (ret < 0) | ||
249 | goto err_out; | ||
250 | |||
251 | ret = -EFAULT; | ||
237 | if (copy_to_user(useraddr, &info, sizeof(info))) | 252 | if (copy_to_user(useraddr, &info, sizeof(info))) |
238 | return -EFAULT; | 253 | goto err_out; |
239 | return 0; | 254 | |
255 | if (rule_buf) { | ||
256 | useraddr += offsetof(struct ethtool_rxnfc, rule_locs); | ||
257 | if (copy_to_user(useraddr, rule_buf, | ||
258 | info.rule_cnt * sizeof(u32))) | ||
259 | goto err_out; | ||
260 | } | ||
261 | ret = 0; | ||
262 | |||
263 | err_out: | ||
264 | if (rule_buf) | ||
265 | kfree(rule_buf); | ||
266 | |||
267 | return ret; | ||
240 | } | 268 | } |
241 | 269 | ||
242 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) | 270 | static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) |
@@ -901,6 +929,10 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
901 | case ETHTOOL_GFLAGS: | 929 | case ETHTOOL_GFLAGS: |
902 | case ETHTOOL_GPFLAGS: | 930 | case ETHTOOL_GPFLAGS: |
903 | case ETHTOOL_GRXFH: | 931 | case ETHTOOL_GRXFH: |
932 | case ETHTOOL_GRXRINGS: | ||
933 | case ETHTOOL_GRXCLSRLCNT: | ||
934 | case ETHTOOL_GRXCLSRULE: | ||
935 | case ETHTOOL_GRXCLSRLALL: | ||
904 | break; | 936 | break; |
905 | default: | 937 | default: |
906 | if (!capable(CAP_NET_ADMIN)) | 938 | if (!capable(CAP_NET_ADMIN)) |
@@ -1052,10 +1084,16 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1052 | dev->ethtool_ops->set_priv_flags); | 1084 | dev->ethtool_ops->set_priv_flags); |
1053 | break; | 1085 | break; |
1054 | case ETHTOOL_GRXFH: | 1086 | case ETHTOOL_GRXFH: |
1055 | rc = ethtool_get_rxhash(dev, useraddr); | 1087 | case ETHTOOL_GRXRINGS: |
1088 | case ETHTOOL_GRXCLSRLCNT: | ||
1089 | case ETHTOOL_GRXCLSRULE: | ||
1090 | case ETHTOOL_GRXCLSRLALL: | ||
1091 | rc = ethtool_get_rxnfc(dev, useraddr); | ||
1056 | break; | 1092 | break; |
1057 | case ETHTOOL_SRXFH: | 1093 | case ETHTOOL_SRXFH: |
1058 | rc = ethtool_set_rxhash(dev, useraddr); | 1094 | case ETHTOOL_SRXCLSRLDEL: |
1095 | case ETHTOOL_SRXCLSRLINS: | ||
1096 | rc = ethtool_set_rxnfc(dev, useraddr); | ||
1059 | break; | 1097 | break; |
1060 | case ETHTOOL_GGRO: | 1098 | case ETHTOOL_GGRO: |
1061 | rc = ethtool_get_gro(dev, useraddr); | 1099 | rc = ethtool_get_gro(dev, useraddr); |