* Protocol handler for Marvell DSA EtherType packets
@ 2008-02-01 13:28 Jesper Dangaard Brouer
2008-02-11 13:18 ` Jesper Dangaard Brouer
0 siblings, 1 reply; 2+ messages in thread
From: Jesper Dangaard Brouer @ 2008-02-01 13:28 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: David S. Miller
Hi Netdev
I writing a new protocol handler using dev_add_pack(). (For a Marvell
switch chip handling DSA (Distributed Switch Architecture) Ethertype
packets).
My protocol handler works and I get the skb. But I want to remove the
DSA Headers and send the packet back for normal processing on a
device. (I actually just want to be able to tcpdump these packets on
the device).
I'm removing the headers by:
skb_pull(skb, sizeof(struct dsa_header));
I'm trying to retransmit it by:
netif_rx(skb);
But it seems that I just retransmit the same packet without removing
the DSA headers.
Any hints about which functions I should use the remove the DSA header?
--
Med venlig hilsen / Best regards
Jesper Brouer
ComX Networks A/S
Linux Network developer
Cand. Scient Datalog / MSc.
Author of http://adsl-optimizer.dk
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Protocol handler for Marvell DSA EtherType packets
2008-02-01 13:28 Protocol handler for Marvell DSA EtherType packets Jesper Dangaard Brouer
@ 2008-02-11 13:18 ` Jesper Dangaard Brouer
0 siblings, 0 replies; 2+ messages in thread
From: Jesper Dangaard Brouer @ 2008-02-11 13:18 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: David S. Miller
[-- Attachment #1: Type: text/plain, Size: 5251 bytes --]
Hi NetDev and Google,
The answer to my question was:
Aha, you are trying to use tcpdump to see the "encapsulated" packets,
then you also need to adjust skb->mac.raw.
I have attached the code (and inlined the receive func, for easier
commenting), as I have another question:
I use dev_get_by_index() which calls dev_hold() (via my function
m88e_get_netdevice()).
The question is:
Should I use dev_put() before or after calling netif_rx(skb).
--
Med venlig hilsen / Best regards
Jesper Brouer
ComX Networks A/S
Linux Network developer
Cand. Scient Datalog / MSc.
Author of http://adsl-optimizer.dk
LinkedIn: http://www.linkedin.com/in/brouer
On Fri, 2008-02-01 at 14:28 +0100, Jesper Dangaard Brouer wrote:
> Hi Netdev
>
> I writing a new protocol handler using dev_add_pack(). (For a Marvell
> switch chip handling DSA (Distributed Switch Architecture) Ethertype
> packets).
>
> My protocol handler works and I get the skb. But I want to remove the
> DSA Headers and send the packet back for normal processing on a
> device. (I actually just want to be able to tcpdump these packets on
> the device).
>
> I'm removing the headers by:
> skb_pull(skb, sizeof(struct dsa_header));
>
> I'm trying to retransmit it by:
> netif_rx(skb);
>
> But it seems that I just retransmit the same packet without removing
> the DSA headers.
>
> Any hints about which functions I should use the remove the DSA header?
/*
* Main DSA Receive routine.
*/
int dsa_receive(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
int res = NET_RX_SUCCESS;
struct dsa_header *dsa_hdr;
struct proto_header *proto_hdr;
struct net_device *port_dev; /* the port associated net_device*/
struct ethhdr *eth_hdr;
/*
if (skb->pkt_type == PACKET_OTHERHOST) VERBOSE("PACKET_OTHERHOST");
else if (skb->pkt_type == PACKET_BROADCAST) VERBOSE("PACKET_BROADCAST");
else if (skb->pkt_type == PACKET_MULTICAST) VERBOSE("PACKET_MULTICAST");
else if (skb->pkt_type == PACKET_HOST) VERBOSE("PACKET_HOST");
else VERBOSE("PACKET_TYPE UNKNOWN");
*/
// Access to the real mac header
eth_hdr = (struct ethhdr *)skb->mac.raw; // Same as eth_hdr(skb)
// At this point the Ethernet header has been removed, but the
// DSA EtherType header contains two extra reserved bytes,
// move the pointer past these.
//
// DEBUGOUT("Removing 2 reserved bytes from DSA EtherType tag");
skb_pull(skb, 2);
// Access to the DSA packet information
dsa_hdr = (struct dsa_header *) skb->data;
if (net_ratelimit()) {
printk(KERN_INFO);
printk("Dev:%s ", skb->dev->name);
printk("Type 0x%x ", dsa_hdr->type);
printk("Tagged 0x%x ", dsa_hdr->tagged);
// printk("Dev 0x%x ", dsa_hdr->dev);
printk("Port 0x%x ", dsa_hdr->port);
printk("Info 0x%x ", dsa_hdr->info);
printk("Prio 0x%x ", dsa_hdr->pri);
printk("Res 0x%x ", dsa_hdr->res);
printk("VLAN ID 0x%x ",dsa_hdr->vid);
printk("\n");
}
// Decoding the DSA type
switch(dsa_hdr->type) {
case DSA_TO_CPU:
{
int code = ((dsa_hdr->info)&0x06)|dsa_hdr->res;
if(IGMP_TRAP == code) {
printk("IGMP Trap\n");
} else {
printk("Unsupported code %d\n",code);
}
break;
}
case DSA_FROM_CPU:
/*Fall through*/
case DSA_TO_SNIFFER:
/*Fall through*/
if (net_ratelimit())
DEBUGOUT("Sniffer packet");
break;
case DSA_FORWARD:
/*Fall through*/
default:
break;
}
// Find the device associated with the switch port.
//
// Q: m88e_get_netdevice() calls dev_get_by_index(), which it calls dev_hold()
port_dev = m88e_get_netdevice(dsa_hdr->port);
skb->dev = port_dev;
// Move past the DSA header
skb_pull(skb, sizeof(struct dsa_header));
// TEST: if it possible to change some skb data and see it in tcpdump
// eth_hdr->h_proto = 0x9111;
/* Extract the ethertype of the encapsulated packet, and
indicate the protocol to the next layer. */
proto_hdr = (struct proto_header*) skb->data;
skb->protocol = proto_hdr->h_proto;
if (net_ratelimit())
printk(KERN_ERR "Encapsulated packet Protocol 0x%x\n",skb->protocol);
// HACK, shift the mac header, this allows packet sniffers to
// decode the packet as a normal ethernet packet, but the mac
// address will not be correct.
skb->mac.raw = skb->data - (6+6);
// Q: Is it allowed to modify the skb data, I would like to
// correct the MAC headers, but is that allowed? Do I need to
// skb_copy the packet?
// Move past the EtherType of the encapsulated packet
skb_pull(skb, sizeof(struct proto_header));
// FIXME: Perhaps we need to change skb->pkt_type to
// PACKET_HOST, to make the next protocol handlers
// accept/process the data???
//skb->pkt_type = PACKET_HOST;
// Retransmit it on a virtual switch port device... this will
// e.g. send it to the IGMP protocol handler.
res = netif_rx(skb);
// Release the device pointer
if (port_dev)
dev_put(port_dev);
return res;
drop:
kfree_skb(skb);
out:
return NET_RX_DROP;
}
static struct packet_type dsa_packet_type =
{
.type = __constant_htons(ETHERTYPE_DSA),
.dev = NULL, /* NULL is wildcarded interfaces */
.func = dsa_receive,
.data = NULL,
//.data = (void*)1, /* Set here '(void *)1' when this code can SHARE SKBs */
.next = NULL
};
[-- Attachment #2: ethertype_dsa.c --]
[-- Type: text/x-csrc, Size: 6773 bytes --]
/*
* Marvell DSA (Distributed Switch Architecture) Ethertype handling.
*
* Some Marvell switch chips support to send/trap/mirror special
* packets to another switch port. These special packets can contain
* some extra information stored in (whats called) a DSA tag. The
* chip also supports adding a special EtherType in front of the DSA
* tag, allowing a CPU (which attached to one of the switch ports)
* easier identification of DSA frames.
*
* Copyright (C) Jesper Dangaard Brouer, Visipia Aps.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* SVN version info:
* $LastChangedDate: 2008-02-11 11:11:28 +0100 (Mon, 11 Feb 2008) $
* $LastChangedRevision: 5238 $
* $LastChangedBy: jdb $
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include "ethertype_dsa.h"
#define MODULE_NAME "m88e_DSA"
#define M88E_DEBUG 1
#define M88E_VERBOSE 1
#include "m88e.h"
#ifndef NOTICE /* Handle if "m88e.h" debug macros are not included */
#define NOTICE(S) printk(KERN_NOTICE "NOTICE: " S "\n")
#define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
#define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A)
#endif/*NOTICE*/
#include <linux/netdevice.h> /* struct packet_type */
#include <linux/if_ether.h> /* struct ethhdr */
#include "m88e_dev.h" /* Access to port associated net_device's */
/*
Default EtherType set by Marvell is 0x9100, this should be changed
1) because its conflicts with double-tagging of VLANs
2) because it hits the same EtherType hash bucket (ptype_base) as IP and VLAN
*/
#define ETHERTYPE_DSA 0x9100
struct proto_header
{
unsigned short h_proto; /* packet type ID field */
} __attribute__((packed));
/*
* Main DSA Receive routine.
*/
int dsa_receive(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
int res = NET_RX_SUCCESS;
struct dsa_header *dsa_hdr;
struct proto_header *proto_hdr;
struct net_device *port_dev; /* the port associated net_device*/
struct ethhdr *eth_hdr;
/*
if (skb->pkt_type == PACKET_OTHERHOST) VERBOSE("PACKET_OTHERHOST");
else if (skb->pkt_type == PACKET_BROADCAST) VERBOSE("PACKET_BROADCAST");
else if (skb->pkt_type == PACKET_MULTICAST) VERBOSE("PACKET_MULTICAST");
else if (skb->pkt_type == PACKET_HOST) VERBOSE("PACKET_HOST");
else VERBOSE("PACKET_TYPE UNKNOWN");
*/
// Access to the real mac header
eth_hdr = (struct ethhdr *)skb->mac.raw; // Same as eth_hdr(skb)
// At this point the Ethernet header has been removed, but the
// DSA EtherType header contains two extra reserved bytes,
// move the pointer past these.
//
// DEBUGOUT("Removing 2 reserved bytes from DSA EtherType tag");
skb_pull(skb, 2);
// Access to the DSA packet information
dsa_hdr = (struct dsa_header *) skb->data;
if (net_ratelimit()) {
printk(KERN_INFO);
printk("Dev:%s ", skb->dev->name);
printk("Type 0x%x ", dsa_hdr->type);
printk("Tagged 0x%x ", dsa_hdr->tagged);
// printk("Dev 0x%x ", dsa_hdr->dev);
printk("Port 0x%x ", dsa_hdr->port);
printk("Info 0x%x ", dsa_hdr->info);
printk("Prio 0x%x ", dsa_hdr->pri);
printk("Res 0x%x ", dsa_hdr->res);
printk("VLAN ID 0x%x ",dsa_hdr->vid);
printk("\n");
}
// Decoding the DSA type
switch(dsa_hdr->type) {
case DSA_TO_CPU:
{
int code = ((dsa_hdr->info)&0x06)|dsa_hdr->res;
if(IGMP_TRAP == code) {
printk("IGMP Trap\n");
} else {
printk("Unsupported code %d\n",code);
}
break;
}
case DSA_FROM_CPU:
/*Fall through*/
case DSA_TO_SNIFFER:
/*Fall through*/
if (net_ratelimit())
DEBUGOUT("Sniffer packet");
break;
case DSA_FORWARD:
/*Fall through*/
default:
break;
}
// Find the device associated with the switch port.
port_dev = m88e_get_netdevice(dsa_hdr->port);
skb->dev = port_dev;
// Move past the DSA header
skb_pull(skb, sizeof(struct dsa_header));
// TEST: if it possible to change some skb data and see it in tcpdump
// eth_hdr->h_proto = 0x9111;
/* Extract the ethertype of the encapsulated packet, and
indicate the protocol to the next layer. */
proto_hdr = (struct proto_header*) skb->data;
skb->protocol = proto_hdr->h_proto;
if (net_ratelimit())
printk(KERN_ERR "Encapsulated packet Protocol 0x%x\n",skb->protocol);
// HACK, shift the mac header, this allows packet sniffers to
// decode the packet as a normal ethernet packet, but the mac
// address will not be correct.
skb->mac.raw = skb->data - (6+6);
// Q: Is it allowed to modify the skb data, I would like to
// correct the MAC headers, but is that allowed? Do I need to
// skb_copy the packet?
// Move past the EtherType of the encapsulated packet
skb_pull(skb, sizeof(struct proto_header));
// FIXME: Perhaps we need to change skb->pkt_type to
// PACKET_HOST, to make the next protocol handlers
// accept/process the data???
//skb->pkt_type = PACKET_HOST;
// Retransmit it on a virtual switch port device... this will
// e.g. send it to the IGMP protocol handler.
res = netif_rx(skb);
// Release the device pointer
if (port_dev)
dev_put(port_dev);
return res;
drop:
kfree_skb(skb);
out:
return NET_RX_DROP;
}
static struct packet_type dsa_packet_type =
{
.type = __constant_htons(ETHERTYPE_DSA),
.dev = NULL, /* NULL is wildcarded interfaces */
.func = dsa_receive,
.data = NULL,
//.data = (void*)1, /* Set here '(void *)1' when this code can SHARE SKBs */
.next = NULL
};
void dsa_register_handler(void)
{
// Only process DSA packets on CPU to switch device, trying to
// avoid loops.
dsa_packet_type.dev = dev_get_by_name("ixp1");
// TODO: Increase the MTU on the receiving device, the DSA
// EtherType is 4 bytes and the DSA info is 4 bytes.
NOTICE("Register: DSA EtherType packet handler");
dev_add_pack(&dsa_packet_type);
}
void dsa_unregister_handler(void)
{
NOTICE("Unregister: DSA EtherType packet handler");
dev_remove_pack(&dsa_packet_type);
}
[-- Attachment #3: ethertype_dsa.h --]
[-- Type: text/x-chdr, Size: 2018 bytes --]
/*
* Marvell DSA (Distributed Switch Architecture) Ethertype handling.
*
* Copyright (C) Jesper Dangaard Brouer, Visipia Aps.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* SVN version info:
* $LastChangedDate: 2008-02-11 11:11:28 +0100 (Mon, 11 Feb 2008) $
* $LastChangedRevision: 5238 $
* $LastChangedBy: jdb $
*
*/
#ifndef _ethertype_dsa_H_
#define _ethertype_dsa_H_
#include <linux/types.h>
#include <asm/byteorder.h>
struct dsa_header {
__u8 type:2,
tagged:1,
dev:5;
__u8 port:5,
info:3; // Decoding dependent on type
#if defined(__BIG_ENDIAN_BITFIELD)
__u16 pri:3,
res:1,
vid:12;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
#error "Not defined for Little Endian CPUs"
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
};
// DSA Tag Types
enum {
DSA_TO_CPU = 0x0, // b00
DSA_FROM_CPU = 0x1, // b01
DSA_TO_SNIFFER = 0x2, // b10
DSA_FORWARD = 0x3, // b11
};
// DSA_TO_CPU Support codes
enum {
BDPU_TRAP = 0x0, // b000
FRAME2REG_RESPONSE = 0x1, // b001
IGMP_TRAP = 0x2, // b010
POLICY_TRAP = 0x3, // b011
ARP_MIRROR = 0x4, // b100
POLICY_MIRROR = 0x5, // b101
};
extern void dsa_register_handler (void);
extern void dsa_unregister_handler(void);
#endif
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-02-11 13:20 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-01 13:28 Protocol handler for Marvell DSA EtherType packets Jesper Dangaard Brouer
2008-02-11 13:18 ` Jesper Dangaard Brouer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).