Commit 59089d8d authored by Santwona Behera's avatar Santwona Behera Committed by David S. Miller

ethtool: Add RX pkt classification interface

Signed-off-by: default avatarSantwona Behera <santwona.behera@sun.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3876732c
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Portions Copyright 2002 Intel (eli.kupermann@intel.com, * Portions Copyright 2002 Intel (eli.kupermann@intel.com,
* christopher.leech@intel.com, * christopher.leech@intel.com,
* scott.feldman@intel.com) * scott.feldman@intel.com)
* Portions Copyright (C) Sun Microsystems 2008
*/ */
#ifndef _LINUX_ETHTOOL_H #ifndef _LINUX_ETHTOOL_H
...@@ -287,10 +288,75 @@ enum ethtool_flags { ...@@ -287,10 +288,75 @@ enum ethtool_flags {
ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */
}; };
/* The following structures are for supporting RX network flow
* classification configuration. Note, all multibyte fields, e.g.,
* ip4src, ip4dst, psrc, pdst, spi, etc. are expected to be in network
* byte order.
*/
struct ethtool_tcpip4_spec {
__be32 ip4src;
__be32 ip4dst;
__be16 psrc;
__be16 pdst;
__u8 tos;
};
struct ethtool_ah_espip4_spec {
__be32 ip4src;
__be32 ip4dst;
__be32 spi;
__u8 tos;
};
struct ethtool_rawip4_spec {
__be32 ip4src;
__be32 ip4dst;
__u8 hdata[64];
};
struct ethtool_ether_spec {
__be16 ether_type;
__u8 frame_size;
__u8 eframe[16];
};
#define ETH_RX_NFC_IP4 1
#define ETH_RX_NFC_IP6 2
struct ethtool_usrip4_spec {
__be32 ip4src;
__be32 ip4dst;
__be32 l4_4_bytes;
__u8 tos;
__u8 ip_ver;
__u8 proto;
};
struct ethtool_rx_flow_spec {
__u32 flow_type;
union {
struct ethtool_tcpip4_spec tcp_ip4_spec;
struct ethtool_tcpip4_spec udp_ip4_spec;
struct ethtool_tcpip4_spec sctp_ip4_spec;
struct ethtool_ah_espip4_spec ah_ip4_spec;
struct ethtool_ah_espip4_spec esp_ip4_spec;
struct ethtool_rawip4_spec raw_ip4_spec;
struct ethtool_ether_spec ether_spec;
struct ethtool_usrip4_spec usr_ip4_spec;
__u8 hdata[64];
} h_u, m_u; /* entry, mask */
__u64 ring_cookie;
__u32 location;
};
struct ethtool_rxnfc { struct ethtool_rxnfc {
__u32 cmd; __u32 cmd;
__u32 flow_type; __u32 flow_type;
/* The rx flow hash value or the rule DB size */
__u64 data; __u64 data;
struct ethtool_rx_flow_spec fs;
__u32 rule_cnt;
__u32 rule_locs[0];
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -417,8 +483,8 @@ struct ethtool_ops { ...@@ -417,8 +483,8 @@ struct ethtool_ops {
/* the following hooks are obsolete */ /* the following hooks are obsolete */
int (*self_test_count)(struct net_device *);/* use get_sset_count */ int (*self_test_count)(struct net_device *);/* use get_sset_count */
int (*get_stats_count)(struct net_device *);/* use get_sset_count */ int (*get_stats_count)(struct net_device *);/* use get_sset_count */
int (*get_rxhash)(struct net_device *, struct ethtool_rxnfc *); int (*get_rxnfc)(struct net_device *, struct ethtool_rxnfc *, void *);
int (*set_rxhash)(struct net_device *, struct ethtool_rxnfc *); int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
}; };
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
...@@ -469,6 +535,12 @@ struct ethtool_ops { ...@@ -469,6 +535,12 @@ struct ethtool_ops {
#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ #define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */
#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */ #define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */
#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */ #define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */
#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */
#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */
#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */
#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */
#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
/* compatibility with older code */ /* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET #define SPARC_ETH_GSET ETHTOOL_GSET
...@@ -565,9 +637,13 @@ struct ethtool_ops { ...@@ -565,9 +637,13 @@ struct ethtool_ops {
#define UDP_V6_FLOW 0x06 #define UDP_V6_FLOW 0x06
#define SCTP_V6_FLOW 0x07 #define SCTP_V6_FLOW 0x07
#define AH_ESP_V6_FLOW 0x08 #define AH_ESP_V6_FLOW 0x08
#define AH_V4_FLOW 0x09
#define ESP_V4_FLOW 0x0a
#define AH_V6_FLOW 0x0b
#define ESP_V6_FLOW 0x0c
#define IP_USER_FLOW 0x0d
/* L3-L4 network traffic flow hash options */ /* L3-L4 network traffic flow hash options */
#define RXH_DEV_PORT (1 << 0)
#define RXH_L2DA (1 << 1) #define RXH_L2DA (1 << 1)
#define RXH_VLAN (1 << 2) #define RXH_VLAN (1 << 2)
#define RXH_L3_PROTO (1 << 3) #define RXH_L3_PROTO (1 << 3)
...@@ -577,5 +653,6 @@ struct ethtool_ops { ...@@ -577,5 +653,6 @@ struct ethtool_ops {
#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ #define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */
#define RXH_DISCARD (1 << 31) #define RXH_DISCARD (1 << 31)
#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL
#endif /* _LINUX_ETHTOOL_H */ #endif /* _LINUX_ETHTOOL_H */
...@@ -209,34 +209,62 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) ...@@ -209,34 +209,62 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)
return 0; return 0;
} }
static int ethtool_set_rxhash(struct net_device *dev, void __user *useraddr) static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr)
{ {
struct ethtool_rxnfc cmd; struct ethtool_rxnfc cmd;
if (!dev->ethtool_ops->set_rxhash) if (!dev->ethtool_ops->set_rxnfc)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (copy_from_user(&cmd, useraddr, sizeof(cmd))) if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
return -EFAULT; return -EFAULT;
return dev->ethtool_ops->set_rxhash(dev, &cmd); return dev->ethtool_ops->set_rxnfc(dev, &cmd);
} }
static int ethtool_get_rxhash(struct net_device *dev, void __user *useraddr) static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr)
{ {
struct ethtool_rxnfc info; struct ethtool_rxnfc info;
const struct ethtool_ops *ops = dev->ethtool_ops;
int ret;
void *rule_buf = NULL;
if (!dev->ethtool_ops->get_rxhash) if (!ops->get_rxnfc)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (copy_from_user(&info, useraddr, sizeof(info))) if (copy_from_user(&info, useraddr, sizeof(info)))
return -EFAULT; return -EFAULT;
dev->ethtool_ops->get_rxhash(dev, &info); if (info.cmd == ETHTOOL_GRXCLSRLALL) {
if (info.rule_cnt > 0) {
rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
GFP_USER);
if (!rule_buf)
return -ENOMEM;
}
}
ret = ops->get_rxnfc(dev, &info, rule_buf);
if (ret < 0)
goto err_out;
ret = -EFAULT;
if (copy_to_user(useraddr, &info, sizeof(info))) if (copy_to_user(useraddr, &info, sizeof(info)))
return -EFAULT; goto err_out;
return 0;
if (rule_buf) {
useraddr += offsetof(struct ethtool_rxnfc, rule_locs);
if (copy_to_user(useraddr, rule_buf,
info.rule_cnt * sizeof(u32)))
goto err_out;
}
ret = 0;
err_out:
if (rule_buf)
kfree(rule_buf);
return ret;
} }
static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 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,6 +929,10 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_GFLAGS: case ETHTOOL_GFLAGS:
case ETHTOOL_GPFLAGS: case ETHTOOL_GPFLAGS:
case ETHTOOL_GRXFH: case ETHTOOL_GRXFH:
case ETHTOOL_GRXRINGS:
case ETHTOOL_GRXCLSRLCNT:
case ETHTOOL_GRXCLSRULE:
case ETHTOOL_GRXCLSRLALL:
break; break;
default: default:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
...@@ -1052,10 +1084,16 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) ...@@ -1052,10 +1084,16 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
dev->ethtool_ops->set_priv_flags); dev->ethtool_ops->set_priv_flags);
break; break;
case ETHTOOL_GRXFH: case ETHTOOL_GRXFH:
rc = ethtool_get_rxhash(dev, useraddr); case ETHTOOL_GRXRINGS:
case ETHTOOL_GRXCLSRLCNT:
case ETHTOOL_GRXCLSRULE:
case ETHTOOL_GRXCLSRLALL:
rc = ethtool_get_rxnfc(dev, useraddr);
break; break;
case ETHTOOL_SRXFH: case ETHTOOL_SRXFH:
rc = ethtool_set_rxhash(dev, useraddr); case ETHTOOL_SRXCLSRLDEL:
case ETHTOOL_SRXCLSRLINS:
rc = ethtool_set_rxnfc(dev, useraddr);
break; break;
case ETHTOOL_GGRO: case ETHTOOL_GGRO:
rc = ethtool_get_gro(dev, useraddr); rc = ethtool_get_gro(dev, useraddr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment