Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: bcm_sf2: Support specifying VLAN tag egress rule

The port to which the ASP is connected on 7278 is not capable of
processing VLAN tags as part of the Ethernet frame, so allow an user to
configure the egress VLAN policy they want to see applied by purposing
the h_ext.data[1] field. Bit 0 is used to indicate that 0=tagged,
1=untagged.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Florian Fainelli and committed by
David S. Miller
8b3abe30 7555020c

+38 -2
+38 -2
drivers/net/dsa/bcm_sf2_cfp.c
··· 13 13 #include <net/dsa.h> 14 14 #include <linux/bitmap.h> 15 15 #include <net/flow_offload.h> 16 + #include <net/switchdev.h> 17 + #include <uapi/linux/if_bridge.h> 16 18 17 19 #include "bcm_sf2.h" 18 20 #include "bcm_sf2_regs.h" ··· 849 847 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 850 848 s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index; 851 849 __u64 ring_cookie = fs->ring_cookie; 850 + struct switchdev_obj_port_vlan vlan; 852 851 unsigned int queue_num, port_num; 852 + u16 vid; 853 853 int ret; 854 854 855 855 /* This rule is a Wake-on-LAN filter and we must specifically ··· 871 867 dsa_is_cpu_port(ds, port_num)) || 872 868 port_num >= priv->hw_params.num_ports) 873 869 return -EINVAL; 870 + 871 + /* If the rule is matching a particular VLAN, make sure that we honor 872 + * the matching and have it tagged or untagged on the destination port, 873 + * we do this on egress with a VLAN entry. The egress tagging attribute 874 + * is expected to be provided in h_ext.data[1] bit 0. A 1 means untagged, 875 + * a 0 means tagged. 876 + */ 877 + if (fs->flow_type & FLOW_EXT) { 878 + /* We cannot support matching multiple VLAN IDs yet */ 879 + if ((be16_to_cpu(fs->m_ext.vlan_tci) & VLAN_VID_MASK) != 880 + VLAN_VID_MASK) 881 + return -EINVAL; 882 + 883 + vid = be16_to_cpu(fs->h_ext.vlan_tci) & VLAN_VID_MASK; 884 + vlan.vid_begin = vid; 885 + vlan.vid_end = vid; 886 + if (cpu_to_be32(fs->h_ext.data[1]) & 1) 887 + vlan.flags = BRIDGE_VLAN_INFO_UNTAGGED; 888 + else 889 + vlan.flags = 0; 890 + 891 + ret = ds->ops->port_vlan_prepare(ds, port_num, &vlan); 892 + if (ret) 893 + return ret; 894 + 895 + ds->ops->port_vlan_add(ds, port_num, &vlan); 896 + } 897 + 874 898 /* 875 899 * We have a small oddity where Port 6 just does not have a 876 900 * valid bit here (so we substract by one). ··· 934 902 int ret = -EINVAL; 935 903 936 904 /* Check for unsupported extensions */ 937 - if ((fs->flow_type & FLOW_MAC_EXT) || 938 - fs->m_ext.data[1]) 905 + if (fs->flow_type & FLOW_MAC_EXT) 939 906 return -EINVAL; 940 907 941 908 if (fs->location != RX_CLS_LOC_ANY && 942 909 fs->location > bcm_sf2_cfp_rule_size(priv)) 943 910 return -EINVAL; 911 + 912 + if ((fs->flow_type & FLOW_EXT) && 913 + !(ds->ops->port_vlan_prepare || ds->ops->port_vlan_add || 914 + ds->ops->port_vlan_del)) 915 + return -EOPNOTSUPP; 944 916 945 917 if (fs->location != RX_CLS_LOC_ANY && 946 918 test_bit(fs->location, priv->cfp.used))