summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Chevallier <maxime.chevallier@bootlin.com>2019-06-27 10:52:26 +0200
committerDavid S. Miller <davem@davemloft.net>2019-06-27 09:38:17 -0700
commit5b9469a285ebc85af29736a6d9fa995aea0dbf0b (patch)
tree277b5366d3418beaaef2905a91fd20177927531e
parent8b89d8dad5df177032e7e97ecfb18f01134e0e4b (diff)
downloadlinux-5b9469a285ebc85af29736a6d9fa995aea0dbf0b.tar.gz
linux-5b9469a285ebc85af29736a6d9fa995aea0dbf0b.tar.bz2
linux-5b9469a285ebc85af29736a6d9fa995aea0dbf0b.zip
net: ethtool: Allow parsing ETHER_FLOW types when using flow_rule
When parsing an ethtool_rx_flow_spec, users can specify an ethernet flow which could contain matches based on the ethernet header, such as the MAC address, the VLAN tag or the ethertype. ETHER_FLOW uses the src and dst ethernet addresses, along with the ethertype as keys. Matches based on the vlan tag are also possible, but they are specified using the special FLOW_EXT flag. Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Acked-by: Pablo Neira Ayuso <pablo@gnumonks.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/ethtool.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4d1011b2e24f..6288e69e94fc 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -2883,6 +2883,30 @@ ethtool_rx_flow_rule_create(const struct ethtool_rx_flow_spec_input *input)
match->mask.basic.n_proto = htons(0xffff);
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) {
+ case ETHER_FLOW: {
+ const struct ethhdr *ether_spec, *ether_m_spec;
+
+ ether_spec = &fs->h_u.ether_spec;
+ ether_m_spec = &fs->m_u.ether_spec;
+
+ if (!is_zero_ether_addr(ether_m_spec->h_source)) {
+ ether_addr_copy(match->key.eth_addrs.src,
+ ether_spec->h_source);
+ ether_addr_copy(match->mask.eth_addrs.src,
+ ether_m_spec->h_source);
+ }
+ if (!is_zero_ether_addr(ether_m_spec->h_dest)) {
+ ether_addr_copy(match->key.eth_addrs.dst,
+ ether_spec->h_dest);
+ ether_addr_copy(match->mask.eth_addrs.dst,
+ ether_m_spec->h_dest);
+ }
+ if (ether_m_spec->h_proto) {
+ match->key.basic.n_proto = ether_spec->h_proto;
+ match->mask.basic.n_proto = ether_m_spec->h_proto;
+ }
+ }
+ break;
case TCP_V4_FLOW:
case UDP_V4_FLOW: {
const struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;