Commit 75a353d4 authored by Eyal Perry's avatar Eyal Perry Committed by David S. Miller

net/mlx4_en: Add RFS support in UDP

Modify RFS code to support applying filters for incoming UDP streams.
Signed-off-by: default avatarEyal Perry <eyalpe@mellanox.com>
Signed-off-by: default avatarAmir Vadai <amirv@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3cdcf133
...@@ -102,6 +102,7 @@ struct mlx4_en_filter { ...@@ -102,6 +102,7 @@ struct mlx4_en_filter {
struct list_head next; struct list_head next;
struct work_struct work; struct work_struct work;
u8 ip_proto;
__be32 src_ip; __be32 src_ip;
__be32 dst_ip; __be32 dst_ip;
__be16 src_port; __be16 src_port;
...@@ -120,14 +121,26 @@ struct mlx4_en_filter { ...@@ -120,14 +121,26 @@ struct mlx4_en_filter {
static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv); static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv);
static enum mlx4_net_trans_rule_id mlx4_ip_proto_to_trans_rule_id(u8 ip_proto)
{
switch (ip_proto) {
case IPPROTO_UDP:
return MLX4_NET_TRANS_RULE_ID_UDP;
case IPPROTO_TCP:
return MLX4_NET_TRANS_RULE_ID_TCP;
default:
return -EPROTONOSUPPORT;
}
};
static void mlx4_en_filter_work(struct work_struct *work) static void mlx4_en_filter_work(struct work_struct *work)
{ {
struct mlx4_en_filter *filter = container_of(work, struct mlx4_en_filter *filter = container_of(work,
struct mlx4_en_filter, struct mlx4_en_filter,
work); work);
struct mlx4_en_priv *priv = filter->priv; struct mlx4_en_priv *priv = filter->priv;
struct mlx4_spec_list spec_tcp = { struct mlx4_spec_list spec_tcp_udp = {
.id = MLX4_NET_TRANS_RULE_ID_TCP, .id = mlx4_ip_proto_to_trans_rule_id(filter->ip_proto),
{ {
.tcp_udp = { .tcp_udp = {
.dst_port = filter->dst_port, .dst_port = filter->dst_port,
...@@ -163,9 +176,14 @@ static void mlx4_en_filter_work(struct work_struct *work) ...@@ -163,9 +176,14 @@ static void mlx4_en_filter_work(struct work_struct *work)
int rc; int rc;
__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16); __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
if (spec_tcp_udp.id < 0) {
en_warn(priv, "RFS: ignoring unsupported ip protocol (%d)\n",
filter->ip_proto);
goto ignore;
}
list_add_tail(&spec_eth.list, &rule.list); list_add_tail(&spec_eth.list, &rule.list);
list_add_tail(&spec_ip.list, &rule.list); list_add_tail(&spec_ip.list, &rule.list);
list_add_tail(&spec_tcp.list, &rule.list); list_add_tail(&spec_tcp_udp.list, &rule.list);
rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn; rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn;
memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN); memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN);
...@@ -183,6 +201,7 @@ static void mlx4_en_filter_work(struct work_struct *work) ...@@ -183,6 +201,7 @@ static void mlx4_en_filter_work(struct work_struct *work)
if (rc) if (rc)
en_err(priv, "Error attaching flow. err = %d\n", rc); en_err(priv, "Error attaching flow. err = %d\n", rc);
ignore:
mlx4_en_filter_rfs_expire(priv); mlx4_en_filter_rfs_expire(priv);
filter->activated = 1; filter->activated = 1;
...@@ -206,8 +225,8 @@ filter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip, ...@@ -206,8 +225,8 @@ filter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
static struct mlx4_en_filter * static struct mlx4_en_filter *
mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip, mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
__be32 dst_ip, __be16 src_port, __be16 dst_port, __be32 dst_ip, u8 ip_proto, __be16 src_port,
u32 flow_id) __be16 dst_port, u32 flow_id)
{ {
struct mlx4_en_filter *filter = NULL; struct mlx4_en_filter *filter = NULL;
...@@ -221,6 +240,7 @@ mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip, ...@@ -221,6 +240,7 @@ mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
filter->src_ip = src_ip; filter->src_ip = src_ip;
filter->dst_ip = dst_ip; filter->dst_ip = dst_ip;
filter->ip_proto = ip_proto;
filter->src_port = src_port; filter->src_port = src_port;
filter->dst_port = dst_port; filter->dst_port = dst_port;
...@@ -252,7 +272,7 @@ static void mlx4_en_filter_free(struct mlx4_en_filter *filter) ...@@ -252,7 +272,7 @@ static void mlx4_en_filter_free(struct mlx4_en_filter *filter)
static inline struct mlx4_en_filter * static inline struct mlx4_en_filter *
mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip, mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
__be16 src_port, __be16 dst_port) u8 ip_proto, __be16 src_port, __be16 dst_port)
{ {
struct mlx4_en_filter *filter; struct mlx4_en_filter *filter;
struct mlx4_en_filter *ret = NULL; struct mlx4_en_filter *ret = NULL;
...@@ -263,6 +283,7 @@ mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip, ...@@ -263,6 +283,7 @@ mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
filter_chain) { filter_chain) {
if (filter->src_ip == src_ip && if (filter->src_ip == src_ip &&
filter->dst_ip == dst_ip && filter->dst_ip == dst_ip &&
filter->ip_proto == ip_proto &&
filter->src_port == src_port && filter->src_port == src_port &&
filter->dst_port == dst_port) { filter->dst_port == dst_port) {
ret = filter; ret = filter;
...@@ -281,6 +302,7 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, ...@@ -281,6 +302,7 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
struct mlx4_en_filter *filter; struct mlx4_en_filter *filter;
const struct iphdr *ip; const struct iphdr *ip;
const __be16 *ports; const __be16 *ports;
u8 ip_proto;
__be32 src_ip; __be32 src_ip;
__be32 dst_ip; __be32 dst_ip;
__be16 src_port; __be16 src_port;
...@@ -295,18 +317,19 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, ...@@ -295,18 +317,19 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
if (ip_is_fragment(ip)) if (ip_is_fragment(ip))
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
if ((ip->protocol != IPPROTO_TCP) && (ip->protocol != IPPROTO_UDP))
return -EPROTONOSUPPORT;
ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
ip_proto = ip->protocol;
src_ip = ip->saddr; src_ip = ip->saddr;
dst_ip = ip->daddr; dst_ip = ip->daddr;
src_port = ports[0]; src_port = ports[0];
dst_port = ports[1]; dst_port = ports[1];
if (ip->protocol != IPPROTO_TCP)
return -EPROTONOSUPPORT;
spin_lock_bh(&priv->filters_lock); spin_lock_bh(&priv->filters_lock);
filter = mlx4_en_filter_find(priv, src_ip, dst_ip, src_port, dst_port); filter = mlx4_en_filter_find(priv, src_ip, dst_ip, ip_proto,
src_port, dst_port);
if (filter) { if (filter) {
if (filter->rxq_index == rxq_index) if (filter->rxq_index == rxq_index)
goto out; goto out;
...@@ -314,7 +337,7 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, ...@@ -314,7 +337,7 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
filter->rxq_index = rxq_index; filter->rxq_index = rxq_index;
} else { } else {
filter = mlx4_en_filter_alloc(priv, rxq_index, filter = mlx4_en_filter_alloc(priv, rxq_index,
src_ip, dst_ip, src_ip, dst_ip, ip_proto,
src_port, dst_port, flow_id); src_port, dst_port, flow_id);
if (!filter) { if (!filter) {
ret = -ENOMEM; ret = -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment