0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/skbuff.h>
0012 #include <net/dsa.h>
0013
0014 #include "dsa_priv.h"
0015
0016 #define HELLCREEK_TAG_LEN 1
0017
0018 static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
0019 struct net_device *dev)
0020 {
0021 struct dsa_port *dp = dsa_slave_to_port(dev);
0022 u8 *tag;
0023
0024
0025
0026
0027
0028 if (skb->ip_summed == CHECKSUM_PARTIAL &&
0029 skb_checksum_help(skb))
0030 return NULL;
0031
0032
0033 tag = skb_put(skb, HELLCREEK_TAG_LEN);
0034 *tag = BIT(dp->index);
0035
0036 return skb;
0037 }
0038
0039 static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
0040 struct net_device *dev)
0041 {
0042
0043 u8 *tag = skb_tail_pointer(skb) - HELLCREEK_TAG_LEN;
0044 unsigned int port = tag[0] & 0x03;
0045
0046 skb->dev = dsa_master_find_slave(dev, 0, port);
0047 if (!skb->dev) {
0048 netdev_warn_once(dev, "Failed to get source port: %d\n", port);
0049 return NULL;
0050 }
0051
0052 pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN);
0053
0054 dsa_default_offload_fwd_mark(skb);
0055
0056 return skb;
0057 }
0058
0059 static const struct dsa_device_ops hellcreek_netdev_ops = {
0060 .name = "hellcreek",
0061 .proto = DSA_TAG_PROTO_HELLCREEK,
0062 .xmit = hellcreek_xmit,
0063 .rcv = hellcreek_rcv,
0064 .needed_tailroom = HELLCREEK_TAG_LEN,
0065 };
0066
0067 MODULE_LICENSE("Dual MIT/GPL");
0068 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_HELLCREEK);
0069
0070 module_dsa_tag_driver(hellcreek_netdev_ops);