aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4
diff options
context:
space:
mode:
authorEyal Perry <eyalpe@mellanox.com>2013-11-07 05:19:49 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-07 19:22:47 -0500
commit75a353d4761ae25f5b7676720bab81a8ad2abf0b (patch)
tree49a52772ba34a96f5294a21f0b1b264b5dc81800 /drivers/net/ethernet/mellanox/mlx4
parent3cdcf1334cd76bbcabd0f273ee9a13e4cc7816bc (diff)
net/mlx4_en: Add RFS support in UDP
Modify RFS code to support applying filters for incoming UDP streams. Signed-off-by: Eyal Perry <eyalpe@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index b5554121aca4..cd61e26f434d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -102,6 +102,7 @@ struct mlx4_en_filter {
102 struct list_head next; 102 struct list_head next;
103 struct work_struct work; 103 struct work_struct work;
104 104
105 u8 ip_proto;
105 __be32 src_ip; 106 __be32 src_ip;
106 __be32 dst_ip; 107 __be32 dst_ip;
107 __be16 src_port; 108 __be16 src_port;
@@ -120,14 +121,26 @@ struct mlx4_en_filter {
120 121
121static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv); 122static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv);
122 123
124static enum mlx4_net_trans_rule_id mlx4_ip_proto_to_trans_rule_id(u8 ip_proto)
125{
126 switch (ip_proto) {
127 case IPPROTO_UDP:
128 return MLX4_NET_TRANS_RULE_ID_UDP;
129 case IPPROTO_TCP:
130 return MLX4_NET_TRANS_RULE_ID_TCP;
131 default:
132 return -EPROTONOSUPPORT;
133 }
134};
135
123static void mlx4_en_filter_work(struct work_struct *work) 136static void mlx4_en_filter_work(struct work_struct *work)
124{ 137{
125 struct mlx4_en_filter *filter = container_of(work, 138 struct mlx4_en_filter *filter = container_of(work,
126 struct mlx4_en_filter, 139 struct mlx4_en_filter,
127 work); 140 work);
128 struct mlx4_en_priv *priv = filter->priv; 141 struct mlx4_en_priv *priv = filter->priv;
129 struct mlx4_spec_list spec_tcp = { 142 struct mlx4_spec_list spec_tcp_udp = {
130 .id = MLX4_NET_TRANS_RULE_ID_TCP, 143 .id = mlx4_ip_proto_to_trans_rule_id(filter->ip_proto),
131 { 144 {
132 .tcp_udp = { 145 .tcp_udp = {
133 .dst_port = filter->dst_port, 146 .dst_port = filter->dst_port,
@@ -163,9 +176,14 @@ static void mlx4_en_filter_work(struct work_struct *work)
163 int rc; 176 int rc;
164 __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16); 177 __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
165 178
179 if (spec_tcp_udp.id < 0) {
180 en_warn(priv, "RFS: ignoring unsupported ip protocol (%d)\n",
181 filter->ip_proto);
182 goto ignore;
183 }
166 list_add_tail(&spec_eth.list, &rule.list); 184 list_add_tail(&spec_eth.list, &rule.list);
167 list_add_tail(&spec_ip.list, &rule.list); 185 list_add_tail(&spec_ip.list, &rule.list);
168 list_add_tail(&spec_tcp.list, &rule.list); 186 list_add_tail(&spec_tcp_udp.list, &rule.list);
169 187
170 rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn; 188 rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn;
171 memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN); 189 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 if (rc) 201 if (rc)
184 en_err(priv, "Error attaching flow. err = %d\n", rc); 202 en_err(priv, "Error attaching flow. err = %d\n", rc);
185 203
204ignore:
186 mlx4_en_filter_rfs_expire(priv); 205 mlx4_en_filter_rfs_expire(priv);
187 206
188 filter->activated = 1; 207 filter->activated = 1;
@@ -206,8 +225,8 @@ filter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
206 225
207static struct mlx4_en_filter * 226static struct mlx4_en_filter *
208mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip, 227mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
209 __be32 dst_ip, __be16 src_port, __be16 dst_port, 228 __be32 dst_ip, u8 ip_proto, __be16 src_port,
210 u32 flow_id) 229 __be16 dst_port, u32 flow_id)
211{ 230{
212 struct mlx4_en_filter *filter = NULL; 231 struct mlx4_en_filter *filter = NULL;
213 232
@@ -221,6 +240,7 @@ mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
221 240
222 filter->src_ip = src_ip; 241 filter->src_ip = src_ip;
223 filter->dst_ip = dst_ip; 242 filter->dst_ip = dst_ip;
243 filter->ip_proto = ip_proto;
224 filter->src_port = src_port; 244 filter->src_port = src_port;
225 filter->dst_port = dst_port; 245 filter->dst_port = dst_port;
226 246
@@ -252,7 +272,7 @@ static void mlx4_en_filter_free(struct mlx4_en_filter *filter)
252 272
253static inline struct mlx4_en_filter * 273static inline struct mlx4_en_filter *
254mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip, 274mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
255 __be16 src_port, __be16 dst_port) 275 u8 ip_proto, __be16 src_port, __be16 dst_port)
256{ 276{
257 struct mlx4_en_filter *filter; 277 struct mlx4_en_filter *filter;
258 struct mlx4_en_filter *ret = NULL; 278 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 filter_chain) { 283 filter_chain) {
264 if (filter->src_ip == src_ip && 284 if (filter->src_ip == src_ip &&
265 filter->dst_ip == dst_ip && 285 filter->dst_ip == dst_ip &&
286 filter->ip_proto == ip_proto &&
266 filter->src_port == src_port && 287 filter->src_port == src_port &&
267 filter->dst_port == dst_port) { 288 filter->dst_port == dst_port) {
268 ret = filter; 289 ret = filter;
@@ -281,6 +302,7 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
281 struct mlx4_en_filter *filter; 302 struct mlx4_en_filter *filter;
282 const struct iphdr *ip; 303 const struct iphdr *ip;
283 const __be16 *ports; 304 const __be16 *ports;
305 u8 ip_proto;
284 __be32 src_ip; 306 __be32 src_ip;
285 __be32 dst_ip; 307 __be32 dst_ip;
286 __be16 src_port; 308 __be16 src_port;
@@ -295,18 +317,19 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
295 if (ip_is_fragment(ip)) 317 if (ip_is_fragment(ip))
296 return -EPROTONOSUPPORT; 318 return -EPROTONOSUPPORT;
297 319
320 if ((ip->protocol != IPPROTO_TCP) && (ip->protocol != IPPROTO_UDP))
321 return -EPROTONOSUPPORT;
298 ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); 322 ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
299 323
324 ip_proto = ip->protocol;
300 src_ip = ip->saddr; 325 src_ip = ip->saddr;
301 dst_ip = ip->daddr; 326 dst_ip = ip->daddr;
302 src_port = ports[0]; 327 src_port = ports[0];
303 dst_port = ports[1]; 328 dst_port = ports[1];
304 329
305 if (ip->protocol != IPPROTO_TCP)
306 return -EPROTONOSUPPORT;
307
308 spin_lock_bh(&priv->filters_lock); 330 spin_lock_bh(&priv->filters_lock);
309 filter = mlx4_en_filter_find(priv, src_ip, dst_ip, src_port, dst_port); 331 filter = mlx4_en_filter_find(priv, src_ip, dst_ip, ip_proto,
332 src_port, dst_port);
310 if (filter) { 333 if (filter) {
311 if (filter->rxq_index == rxq_index) 334 if (filter->rxq_index == rxq_index)
312 goto out; 335 goto out;
@@ -314,7 +337,7 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
314 filter->rxq_index = rxq_index; 337 filter->rxq_index = rxq_index;
315 } else { 338 } else {
316 filter = mlx4_en_filter_alloc(priv, rxq_index, 339 filter = mlx4_en_filter_alloc(priv, rxq_index,
317 src_ip, dst_ip, 340 src_ip, dst_ip, ip_proto,
318 src_port, dst_port, flow_id); 341 src_port, dst_port, flow_id);
319 if (!filter) { 342 if (!filter) {
320 ret = -ENOMEM; 343 ret = -ENOMEM;