linux/net/dsa/tag_hellcreek.c
<<
>>
Prefs
   1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
   2/*
   3 * net/dsa/tag_hellcreek.c - Hirschmann Hellcreek switch tag format handling
   4 *
   5 * Copyright (C) 2019,2020 Linutronix GmbH
   6 * Author Kurt Kanzenbach <kurt@linutronix.de>
   7 *
   8 * Based on tag_ksz.c.
   9 */
  10
  11#include <linux/skbuff.h>
  12#include <net/dsa.h>
  13
  14#include "dsa_priv.h"
  15
  16#define HELLCREEK_TAG_LEN       1
  17
  18static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
  19                                      struct net_device *dev)
  20{
  21        struct dsa_port *dp = dsa_slave_to_port(dev);
  22        u8 *tag;
  23
  24        /* Tag encoding */
  25        tag  = skb_put(skb, HELLCREEK_TAG_LEN);
  26        *tag = BIT(dp->index);
  27
  28        return skb;
  29}
  30
  31static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
  32                                     struct net_device *dev,
  33                                     struct packet_type *pt)
  34{
  35        /* Tag decoding */
  36        u8 *tag = skb_tail_pointer(skb) - HELLCREEK_TAG_LEN;
  37        unsigned int port = tag[0] & 0x03;
  38
  39        skb->dev = dsa_master_find_slave(dev, 0, port);
  40        if (!skb->dev) {
  41                netdev_warn(dev, "Failed to get source port: %d\n", port);
  42                return NULL;
  43        }
  44
  45        pskb_trim_rcsum(skb, skb->len - HELLCREEK_TAG_LEN);
  46
  47        skb->offload_fwd_mark = true;
  48
  49        return skb;
  50}
  51
  52static const struct dsa_device_ops hellcreek_netdev_ops = {
  53        .name     = "hellcreek",
  54        .proto    = DSA_TAG_PROTO_HELLCREEK,
  55        .xmit     = hellcreek_xmit,
  56        .rcv      = hellcreek_rcv,
  57        .needed_tailroom = HELLCREEK_TAG_LEN,
  58};
  59
  60MODULE_LICENSE("Dual MIT/GPL");
  61MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_HELLCREEK);
  62
  63module_dsa_tag_driver(hellcreek_netdev_ops);
  64