[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1202735914.20205.32.camel@localhost.localdomain>
Date: Mon, 11 Feb 2008 14:18:34 +0100
From: Jesper Dangaard Brouer <jdb@...x.dk>
To: "netdev@...r.kernel.org" <netdev@...r.kernel.org>
Cc: "David S. Miller" <davem@...emloft.net>
Subject: Re: Protocol handler for Marvell DSA EtherType packets
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
};
View attachment "ethertype_dsa.c" of type "text/x-csrc" (6773 bytes)
View attachment "ethertype_dsa.h" of type "text/x-chdr" (2018 bytes)
Powered by blists - more mailing lists