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

net: dsa: Implement flow dissection for tag_brcm.c

Provide a flow_dissect callback which returns the network offset and
where to find the skb protocol, given the tags structure a common
function works for both tagging formats that are supported.

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

authored by

Florian Fainelli and committed by
David S. Miller
52015366 4076c693

+23
+23
net/dsa/tag_brcm.c
··· 142 142 143 143 return skb; 144 144 } 145 + 146 + static int brcm_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto, 147 + int *offset) 148 + { 149 + /* We have been called on the DSA master network device after 150 + * eth_type_trans() which pulled the Ethernet header already. 151 + * Frames have one of these two layouts: 152 + * ----------------------------------- 153 + * | MAC DA | MAC SA | 4b tag | Type | DSA_TAG_PROTO_BRCM 154 + * ----------------------------------- 155 + * ----------------------------------- 156 + * | 4b tag | MAC DA | MAC SA | Type | DSA_TAG_PROTO_BRCM_PREPEND 157 + * ----------------------------------- 158 + * skb->data points 2 bytes before the actual Ethernet type field and 159 + * we have an offset of 4bytes between where skb->data and where the 160 + * payload starts. 161 + */ 162 + *offset = BRCM_TAG_LEN; 163 + *proto = ((__be16 *)skb->data)[1]; 164 + return 0; 165 + } 145 166 #endif 146 167 147 168 #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) ··· 198 177 .xmit = brcm_tag_xmit, 199 178 .rcv = brcm_tag_rcv, 200 179 .overhead = BRCM_TAG_LEN, 180 + .flow_dissect = brcm_tag_flow_dissect, 201 181 }; 202 182 203 183 DSA_TAG_DRIVER(brcm_netdev_ops); ··· 227 205 .xmit = brcm_tag_xmit_prepend, 228 206 .rcv = brcm_tag_rcv_prepend, 229 207 .overhead = BRCM_TAG_LEN, 208 + .flow_dissect = brcm_tag_flow_dissect, 230 209 }; 231 210 232 211 DSA_TAG_DRIVER(brcm_prepend_netdev_ops);