aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Cree <ecree@solarflare.com>2016-05-26 16:46:05 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-30 01:38:55 -0400
commit68bb399e656f244d3d173a20a8280c167632fca8 (patch)
tree2ed02416436464388146b6b58fde59598b2a2b1f
parent421eeea10d0a5e52256bce9544de477938104fdb (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.c75
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}