diff options
author | Edward Cree <ecree@solarflare.com> | 2016-05-26 16:46:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-30 01:38:55 -0400 |
commit | 68bb399e656f244d3d173a20a8280c167632fca8 (patch) | |
tree | 2ed02416436464388146b6b58fde59598b2a2b1f | |
parent | 421eeea10d0a5e52256bce9544de477938104fdb (diff) |
sfc: use flow dissector helpers for aRFS
Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/sfc/rx.c | 75 |
1 files changed, 21 insertions, 54 deletions
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 8956995b2fe7..9d6cc8b92ba0 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c | |||
@@ -842,33 +842,15 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, | |||
842 | struct efx_nic *efx = netdev_priv(net_dev); | 842 | struct efx_nic *efx = netdev_priv(net_dev); |
843 | struct efx_channel *channel; | 843 | struct efx_channel *channel; |
844 | struct efx_filter_spec spec; | 844 | struct efx_filter_spec spec; |
845 | const __be16 *ports; | 845 | struct flow_keys fk; |
846 | __be16 ether_type; | ||
847 | int nhoff; | ||
848 | int rc; | 846 | int rc; |
849 | 847 | ||
850 | /* The core RPS/RFS code has already parsed and validated | 848 | if (!skb_flow_dissect_flow_keys(skb, &fk, 0)) |
851 | * VLAN, IP and transport headers. We assume they are in the | 849 | return -EPROTONOSUPPORT; |
852 | * header area. | ||
853 | */ | ||
854 | |||
855 | if (skb->protocol == htons(ETH_P_8021Q)) { | ||
856 | const struct vlan_hdr *vh = | ||
857 | (const struct vlan_hdr *)skb->data; | ||
858 | |||
859 | /* We can't filter on the IP 5-tuple and the vlan | ||
860 | * together, so just strip the vlan header and filter | ||
861 | * on the IP part. | ||
862 | */ | ||
863 | EFX_BUG_ON_PARANOID(skb_headlen(skb) < sizeof(*vh)); | ||
864 | ether_type = vh->h_vlan_encapsulated_proto; | ||
865 | nhoff = sizeof(struct vlan_hdr); | ||
866 | } else { | ||
867 | ether_type = skb->protocol; | ||
868 | nhoff = 0; | ||
869 | } | ||
870 | 850 | ||
871 | if (ether_type != htons(ETH_P_IP) && ether_type != htons(ETH_P_IPV6)) | 851 | if (fk.basic.n_proto != htons(ETH_P_IP) && fk.basic.n_proto != htons(ETH_P_IPV6)) |
852 | return -EPROTONOSUPPORT; | ||
853 | if (fk.control.flags & FLOW_DIS_IS_FRAGMENT) | ||
872 | return -EPROTONOSUPPORT; | 854 | return -EPROTONOSUPPORT; |
873 | 855 | ||
874 | efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, | 856 | efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, |
@@ -878,34 +860,19 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, | |||
878 | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | | 860 | EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | |
879 | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT | | 861 | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT | |
880 | EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT; | 862 | EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT; |
881 | spec.ether_type = ether_type; | 863 | spec.ether_type = fk.basic.n_proto; |
882 | 864 | spec.ip_proto = fk.basic.ip_proto; | |
883 | if (ether_type == htons(ETH_P_IP)) { | 865 | |
884 | const struct iphdr *ip = | 866 | if (fk.basic.n_proto == htons(ETH_P_IP)) { |
885 | (const struct iphdr *)(skb->data + nhoff); | 867 | spec.rem_host[0] = fk.addrs.v4addrs.src; |
886 | 868 | spec.loc_host[0] = fk.addrs.v4addrs.dst; | |
887 | EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip)); | ||
888 | if (ip_is_fragment(ip)) | ||
889 | return -EPROTONOSUPPORT; | ||
890 | spec.ip_proto = ip->protocol; | ||
891 | spec.rem_host[0] = ip->saddr; | ||
892 | spec.loc_host[0] = ip->daddr; | ||
893 | EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4); | ||
894 | ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); | ||
895 | } else { | 869 | } else { |
896 | const struct ipv6hdr *ip6 = | 870 | memcpy(spec.rem_host, &fk.addrs.v6addrs.src, sizeof(struct in6_addr)); |
897 | (const struct ipv6hdr *)(skb->data + nhoff); | 871 | memcpy(spec.loc_host, &fk.addrs.v6addrs.dst, sizeof(struct in6_addr)); |
898 | |||
899 | EFX_BUG_ON_PARANOID(skb_headlen(skb) < | ||
900 | nhoff + sizeof(*ip6) + 4); | ||
901 | spec.ip_proto = ip6->nexthdr; | ||
902 | memcpy(spec.rem_host, &ip6->saddr, sizeof(ip6->saddr)); | ||
903 | memcpy(spec.loc_host, &ip6->daddr, sizeof(ip6->daddr)); | ||
904 | ports = (const __be16 *)(ip6 + 1); | ||
905 | } | 872 | } |
906 | 873 | ||
907 | spec.rem_port = ports[0]; | 874 | spec.rem_port = fk.ports.src; |
908 | spec.loc_port = ports[1]; | 875 | spec.loc_port = fk.ports.dst; |
909 | 876 | ||
910 | rc = efx->type->filter_rfs_insert(efx, &spec); | 877 | rc = efx->type->filter_rfs_insert(efx, &spec); |
911 | if (rc < 0) | 878 | if (rc < 0) |
@@ -916,18 +883,18 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, | |||
916 | channel = efx_get_channel(efx, skb_get_rx_queue(skb)); | 883 | channel = efx_get_channel(efx, skb_get_rx_queue(skb)); |
917 | ++channel->rfs_filters_added; | 884 | ++channel->rfs_filters_added; |
918 | 885 | ||
919 | if (ether_type == htons(ETH_P_IP)) | 886 | if (spec.ether_type == htons(ETH_P_IP)) |
920 | netif_info(efx, rx_status, efx->net_dev, | 887 | netif_info(efx, rx_status, efx->net_dev, |
921 | "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n", | 888 | "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n", |
922 | (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP", | 889 | (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP", |
923 | spec.rem_host, ntohs(ports[0]), spec.loc_host, | 890 | spec.rem_host, ntohs(spec.rem_port), spec.loc_host, |
924 | ntohs(ports[1]), rxq_index, flow_id, rc); | 891 | ntohs(spec.loc_port), rxq_index, flow_id, rc); |
925 | else | 892 | else |
926 | netif_info(efx, rx_status, efx->net_dev, | 893 | netif_info(efx, rx_status, efx->net_dev, |
927 | "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n", | 894 | "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n", |
928 | (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP", | 895 | (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP", |
929 | spec.rem_host, ntohs(ports[0]), spec.loc_host, | 896 | spec.rem_host, ntohs(spec.rem_port), spec.loc_host, |
930 | ntohs(ports[1]), rxq_index, flow_id, rc); | 897 | ntohs(spec.loc_port), rxq_index, flow_id, rc); |
931 | 898 | ||
932 | return rc; | 899 | return rc; |
933 | } | 900 | } |