aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/ethtool.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-12-07 14:11:26 -0500
committerBen Hutchings <bhutchings@solarflare.com>2010-12-07 14:11:26 -0500
commitc39d35ebffeea5996a6f8fd8430fae9acfb8aeaf (patch)
treeaf09ac5b15429b41d4b5c54fd63c1ac769d67b39 /drivers/net/sfc/ethtool.c
parent8891681af928f1da795cd4bd59043e5e0fadd6c8 (diff)
sfc: Generalise filter spec initialisation
Move search_depth arrays into per-table state. Define initialisation function efx_filter_init_rx() which sets everything apart from the match fields. Define efx_filter_set_{ipv4_local,ipv4_full,eth_local}() to set the match fields. This allows some simplification of callers and later support for additional protocols and more flexible matching using multiple calls to these functions. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/sfc/ethtool.c')
-rw-r--r--drivers/net/sfc/ethtool.c82
1 files changed, 36 insertions, 46 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 0f46c1a3171..5e50e57b0ae 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -11,6 +11,7 @@
11#include <linux/netdevice.h> 11#include <linux/netdevice.h>
12#include <linux/ethtool.h> 12#include <linux/ethtool.h>
13#include <linux/rtnetlink.h> 13#include <linux/rtnetlink.h>
14#include <linux/in.h>
14#include "net_driver.h" 15#include "net_driver.h"
15#include "workarounds.h" 16#include "workarounds.h"
16#include "selftest.h" 17#include "selftest.h"
@@ -920,6 +921,7 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
920 struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec; 921 struct ethhdr *mac_entry = &ntuple->fs.h_u.ether_spec;
921 struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec; 922 struct ethhdr *mac_mask = &ntuple->fs.m_u.ether_spec;
922 struct efx_filter_spec filter; 923 struct efx_filter_spec filter;
924 int rc;
923 925
924 /* Range-check action */ 926 /* Range-check action */
925 if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR || 927 if (ntuple->fs.action < ETHTOOL_RXNTUPLE_ACTION_CLEAR ||
@@ -929,9 +931,16 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
929 if (~ntuple->fs.data_mask) 931 if (~ntuple->fs.data_mask)
930 return -EINVAL; 932 return -EINVAL;
931 933
934 efx_filter_init_rx(&filter, EFX_FILTER_PRI_MANUAL, 0,
935 (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) ?
936 0xfff : ntuple->fs.action);
937
932 switch (ntuple->fs.flow_type) { 938 switch (ntuple->fs.flow_type) {
933 case TCP_V4_FLOW: 939 case TCP_V4_FLOW:
934 case UDP_V4_FLOW: 940 case UDP_V4_FLOW: {
941 u8 proto = (ntuple->fs.flow_type == TCP_V4_FLOW ?
942 IPPROTO_TCP : IPPROTO_UDP);
943
935 /* Must match all of destination, */ 944 /* Must match all of destination, */
936 if (ip_mask->ip4dst | ip_mask->pdst) 945 if (ip_mask->ip4dst | ip_mask->pdst)
937 return -EINVAL; 946 return -EINVAL;
@@ -943,7 +952,22 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
943 /* and nothing else */ 952 /* and nothing else */
944 if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask) 953 if ((u8)~ip_mask->tos | (u16)~ntuple->fs.vlan_tag_mask)
945 return -EINVAL; 954 return -EINVAL;
955
956 if (!ip_mask->ip4src)
957 rc = efx_filter_set_ipv4_full(&filter, proto,
958 ip_entry->ip4dst,
959 ip_entry->pdst,
960 ip_entry->ip4src,
961 ip_entry->psrc);
962 else
963 rc = efx_filter_set_ipv4_local(&filter, proto,
964 ip_entry->ip4dst,
965 ip_entry->pdst);
966 if (rc)
967 return rc;
946 break; 968 break;
969 }
970
947 case ETHER_FLOW: 971 case ETHER_FLOW:
948 /* Must match all of destination, */ 972 /* Must match all of destination, */
949 if (!is_zero_ether_addr(mac_mask->h_dest)) 973 if (!is_zero_ether_addr(mac_mask->h_dest))
@@ -956,58 +980,24 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
956 if (!is_broadcast_ether_addr(mac_mask->h_source) || 980 if (!is_broadcast_ether_addr(mac_mask->h_source) ||
957 mac_mask->h_proto != htons(0xffff)) 981 mac_mask->h_proto != htons(0xffff))
958 return -EINVAL; 982 return -EINVAL;
983
984 rc = efx_filter_set_eth_local(
985 &filter,
986 (ntuple->fs.vlan_tag_mask == 0xf000) ?
987 ntuple->fs.vlan_tag : EFX_FILTER_VID_UNSPEC,
988 mac_entry->h_dest);
989 if (rc)
990 return rc;
959 break; 991 break;
992
960 default: 993 default:
961 return -EINVAL; 994 return -EINVAL;
962 } 995 }
963 996
964 filter.priority = EFX_FILTER_PRI_MANUAL; 997 if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR)
965 filter.flags = 0;
966
967 switch (ntuple->fs.flow_type) {
968 case TCP_V4_FLOW:
969 if (!ip_mask->ip4src)
970 efx_filter_set_rx_tcp_full(&filter,
971 htonl(ip_entry->ip4src),
972 htons(ip_entry->psrc),
973 htonl(ip_entry->ip4dst),
974 htons(ip_entry->pdst));
975 else
976 efx_filter_set_rx_tcp_wild(&filter,
977 htonl(ip_entry->ip4dst),
978 htons(ip_entry->pdst));
979 break;
980 case UDP_V4_FLOW:
981 if (!ip_mask->ip4src)
982 efx_filter_set_rx_udp_full(&filter,
983 htonl(ip_entry->ip4src),
984 htons(ip_entry->psrc),
985 htonl(ip_entry->ip4dst),
986 htons(ip_entry->pdst));
987 else
988 efx_filter_set_rx_udp_wild(&filter,
989 htonl(ip_entry->ip4dst),
990 htons(ip_entry->pdst));
991 break;
992 case ETHER_FLOW:
993 if (ntuple->fs.vlan_tag_mask == 0xf000)
994 efx_filter_set_rx_mac_full(&filter,
995 ntuple->fs.vlan_tag & 0xfff,
996 mac_entry->h_dest);
997 else
998 efx_filter_set_rx_mac_wild(&filter, mac_entry->h_dest);
999 break;
1000 }
1001
1002 if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_CLEAR) {
1003 return efx_filter_remove_filter(efx, &filter); 998 return efx_filter_remove_filter(efx, &filter);
1004 } else { 999 else
1005 if (ntuple->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
1006 filter.dmaq_id = 0xfff;
1007 else
1008 filter.dmaq_id = ntuple->fs.action;
1009 return efx_filter_insert_filter(efx, &filter, true); 1000 return efx_filter_insert_filter(efx, &filter, true);
1010 }
1011} 1001}
1012 1002
1013static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, 1003static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,