diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-12-07 14:11:26 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2010-12-07 14:11:26 -0500 |
commit | c39d35ebffeea5996a6f8fd8430fae9acfb8aeaf (patch) | |
tree | af09ac5b15429b41d4b5c54fd63c1ac769d67b39 /drivers/net/sfc/ethtool.c | |
parent | 8891681af928f1da795cd4bd59043e5e0fadd6c8 (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.c | 82 |
1 files changed, 36 insertions, 46 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 0f46c1a3171e..5e50e57b0ae2 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 | ||
1013 | static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, | 1003 | static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, |