aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHadar Hen Zion <hadarh@mellanox.com>2013-01-30 18:07:04 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-31 12:48:46 -0500
commitf90a36734a6a0d843baa37b7caa1ef020f799d47 (patch)
tree9bf21e86f331a6719cfa7b324a6b2702c82a5030
parent248c62aa12a318fe53bf4f530b69b150c34416e7 (diff)
net/mlx4_en: Fix ip/udp steering rules multicast mac when attached via ethtool
Destination mac is a mandatory specification for ip/udp steering rules. When attaching multicast steering rules via ethtool the unicast mac of the interface was added to the rule specification instead of the multicast mac. The following commit sets the corresponding multicast mac for the rule multicast ip. Signed-off-by: Hadar Hen Zion <hadarh@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c119
1 files changed, 82 insertions, 37 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 03447dad07e9..86afb5b0e0fa 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -35,6 +35,8 @@
35#include <linux/ethtool.h> 35#include <linux/ethtool.h>
36#include <linux/netdevice.h> 36#include <linux/netdevice.h>
37#include <linux/mlx4/driver.h> 37#include <linux/mlx4/driver.h>
38#include <linux/in.h>
39#include <net/ip.h>
38 40
39#include "mlx4_en.h" 41#include "mlx4_en.h"
40#include "en_port.h" 42#include "en_port.h"
@@ -672,19 +674,71 @@ static int mlx4_en_validate_flow(struct net_device *dev,
672 return 0; 674 return 0;
673} 675}
674 676
677static int mlx4_en_ethtool_add_mac_rule(struct ethtool_rxnfc *cmd,
678 struct list_head *rule_list_h,
679 struct mlx4_spec_list *spec_l2,
680 unsigned char *mac)
681{
682 int err = 0;
683 __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
684
685 spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH;
686 memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN);
687 memcpy(spec_l2->eth.dst_mac, mac, ETH_ALEN);
688
689 if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) {
690 spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci;
691 spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff);
692 }
693
694 list_add_tail(&spec_l2->list, rule_list_h);
695
696 return err;
697}
698
699static int mlx4_en_ethtool_add_mac_rule_by_ipv4(struct mlx4_en_priv *priv,
700 struct ethtool_rxnfc *cmd,
701 struct list_head *rule_list_h,
702 struct mlx4_spec_list *spec_l2,
703 __be32 ipv4_dst)
704{
705 __be64 be_mac = 0;
706 unsigned char mac[ETH_ALEN];
707
708 if (!ipv4_is_multicast(ipv4_dst)) {
709 if (cmd->fs.flow_type & FLOW_MAC_EXT) {
710 memcpy(&mac, cmd->fs.h_ext.h_dest, ETH_ALEN);
711 } else {
712 be_mac = cpu_to_be64((priv->mac & MLX4_MAC_MASK) << 16);
713 memcpy(&mac, &be_mac, ETH_ALEN);
714 }
715 } else {
716 ip_eth_mc_map(ipv4_dst, mac);
717 }
718
719 return mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &mac[0]);
720}
721
675static int add_ip_rule(struct mlx4_en_priv *priv, 722static int add_ip_rule(struct mlx4_en_priv *priv,
676 struct ethtool_rxnfc *cmd, 723 struct ethtool_rxnfc *cmd,
677 struct list_head *list_h) 724 struct list_head *list_h)
678{ 725{
679 struct mlx4_spec_list *spec_l3; 726 struct mlx4_spec_list *spec_l2 = NULL;
727 struct mlx4_spec_list *spec_l3 = NULL;
680 struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec; 728 struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec;
681 729
682 spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); 730 spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
683 if (!spec_l3) { 731 spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
732 if (!spec_l2 || !spec_l3) {
684 en_err(priv, "Fail to alloc ethtool rule.\n"); 733 en_err(priv, "Fail to alloc ethtool rule.\n");
734 kfree(spec_l2);
735 kfree(spec_l3);
685 return -ENOMEM; 736 return -ENOMEM;
686 } 737 }
687 738
739 mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2,
740 cmd->fs.h_u.
741 usr_ip4_spec.ip4dst);
688 spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; 742 spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;
689 spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src; 743 spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src;
690 if (l3_mask->ip4src) 744 if (l3_mask->ip4src)
@@ -701,14 +755,17 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv,
701 struct ethtool_rxnfc *cmd, 755 struct ethtool_rxnfc *cmd,
702 struct list_head *list_h, int proto) 756 struct list_head *list_h, int proto)
703{ 757{
704 struct mlx4_spec_list *spec_l3; 758 struct mlx4_spec_list *spec_l2 = NULL;
705 struct mlx4_spec_list *spec_l4; 759 struct mlx4_spec_list *spec_l3 = NULL;
760 struct mlx4_spec_list *spec_l4 = NULL;
706 struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec; 761 struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec;
707 762
708 spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); 763 spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
709 spec_l4 = kzalloc(sizeof *spec_l4, GFP_KERNEL); 764 spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
710 if (!spec_l4 || !spec_l3) { 765 spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL);
766 if (!spec_l2 || !spec_l3 || !spec_l4) {
711 en_err(priv, "Fail to alloc ethtool rule.\n"); 767 en_err(priv, "Fail to alloc ethtool rule.\n");
768 kfree(spec_l2);
712 kfree(spec_l3); 769 kfree(spec_l3);
713 kfree(spec_l4); 770 kfree(spec_l4);
714 return -ENOMEM; 771 return -ENOMEM;
@@ -717,12 +774,20 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv,
717 spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; 774 spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;
718 775
719 if (proto == TCP_V4_FLOW) { 776 if (proto == TCP_V4_FLOW) {
777 mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,
778 spec_l2,
779 cmd->fs.h_u.
780 tcp_ip4_spec.ip4dst);
720 spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP; 781 spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP;
721 spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src; 782 spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src;
722 spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst; 783 spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst;
723 spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc; 784 spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc;
724 spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst; 785 spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst;
725 } else { 786 } else {
787 mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,
788 spec_l2,
789 cmd->fs.h_u.
790 udp_ip4_spec.ip4dst);
726 spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP; 791 spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP;
727 spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src; 792 spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src;
728 spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst; 793 spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst;
@@ -751,43 +816,23 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,
751 struct list_head *rule_list_h) 816 struct list_head *rule_list_h)
752{ 817{
753 int err; 818 int err;
754 __be64 be_mac;
755 struct ethhdr *eth_spec; 819 struct ethhdr *eth_spec;
756 struct mlx4_en_priv *priv = netdev_priv(dev);
757 struct mlx4_spec_list *spec_l2; 820 struct mlx4_spec_list *spec_l2;
758 __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); 821 struct mlx4_en_priv *priv = netdev_priv(dev);
759 822
760 err = mlx4_en_validate_flow(dev, cmd); 823 err = mlx4_en_validate_flow(dev, cmd);
761 if (err) 824 if (err)
762 return err; 825 return err;
763 826
764 spec_l2 = kzalloc(sizeof *spec_l2, GFP_KERNEL);
765 if (!spec_l2)
766 return -ENOMEM;
767
768 if (cmd->fs.flow_type & FLOW_MAC_EXT) {