diff options
Diffstat (limited to 'drivers')
| -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 | } |
