aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantwona Behera <santwona.behera@sun.com>2009-02-20 03:58:13 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-20 03:58:13 -0500
commit59089d8d162ddcb5c434672e915331964d38a754 (patch)
tree2d2595beffc410caa8054922976206fb600f8750
parent3876732c12cd2b9896e8c3e86fad142112e93569 (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>
-rw-r--r--include/linux/ethtool.h89
-rw-r--r--net/core/ethtool.c58
2 files changed, 131 insertions, 16 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 27c67a542235..131b127b70f8 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -7,6 +7,7 @@
7 * Portions Copyright 2002 Intel (eli.kupermann@intel.com, 7 * Portions Copyright 2002 Intel (eli.kupermann@intel.com,
8 * christopher.leech@intel.com, 8 * christopher.leech@intel.com,
9 * scott.feldman@intel.com) 9 * scott.feldman@intel.com)
10 * Portions Copyright (C) Sun Microsystems 2008
10 */ 11 */
11 12
12#ifndef _LINUX_ETHTOOL_H 13#ifndef _LINUX_ETHTOOL_H
@@ -287,10 +288,75 @@ enum ethtool_flags {
287 ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ 288 ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */
288}; 289};
289 290
290struct ethtool_rxnfc { 291/* The following structures are for supporting RX network flow
291 __u32 cmd; 292 * classification configuration. Note, all multibyte fields, e.g.,
293 * ip4src, ip4dst, psrc, pdst, spi, etc. are expected to be in network
294 * byte order.
295 */
296struct ethtool_tcpip4_spec {
297 __be32 ip4src;
298 __be32 ip4dst;
299 __be16 psrc;
300 __be16 pdst;
301 __u8 tos;
302};
303
304struct ethtool_ah_espip4_spec {
305 __be32 ip4src;
306 __be32 ip4dst;
307 __be32 spi;
308 __u8 tos;
309};
310
311struct ethtool_rawip4_spec {
312 __be32 ip4src;
313 __be32 ip4dst;
314 __u8 hdata[64];
315};
316
317struct ethtool_ether_spec {
318 __be16 ether_type;
319 __u8 frame_size;
320 __u8 eframe[16];
321};
322
323#define ETH_RX_NFC_IP4 1
324#define ETH_RX_NFC_IP6 2
325
326struct ethtool_usrip4_spec {
327 __be32 ip4src;
328 __be32 ip4dst;
329 __be32 l4_4_bytes;
330 __u8 tos;
331 __u8 ip_ver;
332 __u8 proto;
333};
334
335struct ethtool_rx_flow_spec {
292 __u32 flow_type; 336 __u32 flow_type;
293 __u64 data; 337 union {
338 struct ethtool_tcpip4_spec tcp_ip4_spec;
339 struct ethtool_tcpip4_spec udp_ip4_spec;
340 struct ethtool_tcpip4_spec sctp_ip4_spec;
341 struct ethtool_ah_espip4_spec ah_ip4_spec;
342 struct ethtool_ah_espip4_spec esp_ip4_spec;
343 struct ethtool_rawip4_spec raw_ip4_spec;
344 struct ethtool_ether_spec ether_spec;
345 struct ethtool_usrip4_spec usr_ip4_spec;
346 __u8 hdata[64];
347 } h_u, m_u; /* entry, mask */
348 __u64 ring_cookie;
349 __u32 location;
350};
351
352struct ethtool_rxnfc {
353 __u32 cmd;
354 __u32 flow_type;
355 /* The rx flow hash value or the rule DB size */
356 __u64 data;
357 struct ethtool_rx_flow_spec fs;
358 __u32 rule_cnt;
359 __u32 rule_locs[0];
294}; 360};
295 361
296#ifdef __KERNEL__ 362#ifdef __KERNEL__
@@ -417,8 +483,8 @@ struct ethtool_ops {
417 /* the following hooks are obsolete */ 483 /* the following hooks are obsolete */
418 int (*self_test_count)(struct net_device *);/* use get_sset_count */ 484 int (*self_test_count)(struct net_device *);/* use get_sset_count */
419 int (*get_stats_count)(struct net_device *);/* use get_sset_count */ 485 int (*get_stats_count)(struct net_device *);/* use get_sset_count */
420 int (*get_rxhash)(struct net_device *, struct ethtool_rxnfc *); 486 int (*get_rxnfc)(struct net_device *, struct ethtool_rxnfc *, void *);
421 int (*set_rxhash)(struct net_device *, struct ethtool_rxnfc *); 487 int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
422}; 488};
423#endif /* __KERNEL__ */ 489#endif /* __KERNEL__ */
424 490
@@ -469,6 +535,12 @@ struct ethtool_ops {
469#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ 535#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */
470#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */ 536#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */
471#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */ 537#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */
538#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */
539#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */
540#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */
541#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */
542#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */
543#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
472 544
473/* compatibility with older code */ 545/* compatibility with older code */
474#define SPARC_ETH_GSET ETHTOOL_GSET 546#define SPARC_ETH_GSET ETHTOOL_GSET
@@ -565,9 +637,13 @@ struct ethtool_ops {
565#define UDP_V6_FLOW 0x06 637#define UDP_V6_FLOW 0x06
566#define SCTP_V6_FLOW 0x07 638#define SCTP_V6_FLOW 0x07
567#define AH_ESP_V6_FLOW 0x08 639#define AH_ESP_V6_FLOW 0x08
640#define AH_V4_FLOW 0x09
641#define ESP_V4_FLOW 0x0a
642#define AH_V6_FLOW 0x0b
643#define ESP_V6_FLOW 0x0c
644#define IP_USER_FLOW 0x0d
568 645
569/* L3-L4 network traffic flow hash options */ 646/* L3-L4 network traffic flow hash options */
570#define RXH_DEV_PORT (1 << 0)
571#define RXH_L2DA (1 << 1) 647#define RXH_L2DA (1 << 1)
572#define RXH_VLAN (1 << 2) 648#define RXH_VLAN (1 << 2)
573#define RXH_L3_PROTO (1 << 3) 649#define RXH_L3_PROTO (1 << 3)
@@ -577,5 +653,6 @@ struct ethtool_ops {
577#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ 653#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */
578#define RXH_DISCARD (1 << 31) 654#define RXH_DISCARD (1 << 31)
579 655
656#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL
580 657
581#endif /* _LINUX_ETHTOOL_H */ 658#endif /* _LINUX_ETHTOOL_H */
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
212static int ethtool_set_rxhash(struct net_device *dev, void __user *useraddr) 212static 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
225static int ethtool_get_rxhash(struct net_device *dev, void __user *useraddr) 225static 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
263err_out:
264 if (rule_buf)
265 kfree(rule_buf);
266
267 return ret;
240} 268}
241 269
242static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 270static 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);