ebt_vnat -- Slapping on a VLAN tag on the bridge
"Kashyap Ashwin" <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <8FC831532CEE564AB88AC1D999C29DEB02B92F@prinsmail01.am.thmulti.com> |
Hi,
This question is related to "Headroom for bridging question". I wrote a new target to add a VLAN tag to specified packets. This is how you set the rule:
# ebtables -t nat -A POSTROUTING -s 00:11:22:33:44:55 -j vnat --to-vlan 6
Most of the code was simply copied from ebt_s/dnat both in user and kernel code.
This is the problem:
br_netfilter: Argh!! br_nf_post_routing: bad mac.raw pointer.[eth0][br0]
Looks like br_netfilter did not like the fact I did skb_push():
from br_nf_postrouting():
/* Be very paranoid. Must be a device driver bug. */
if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
"bad mac.raw pointer.");
Inside ebt_target_vnat() I am doing the following operations on pskb and returning the info->target if things go well :
if (skb_headroom(*pskb) < VLAN_HLEN) {
struct sk_buff *sk_tmp = *pskb;
printk("%s: In if skb_headroom\n", __FUNCTION__);
*pskb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
kfree_skb(sk_tmp);
if (*pskb == NULL) {
return EBT_DROP;
}
} else {
/* This causes a panic
printk("%s: In else skb_headroom\n", __FUNCTION__);
if (!(*pskb = skb_unshare(*pskb, GFP_ATOMIC))) {
printk(KERN_ERR "vlan: failed to unshare skbuff\n");
return EBT_DROP;
}
*/
}
// This actually pushes skb->data, returns new skb->data
printk("%s: before: mac.raw: %x skb->data: %x\n",
__FUNCTION__, (*pskb)->mac.raw, (*pskb)->data);
veth = (struct vlan_ethhdr *)skb_push(*pskb, VLAN_HLEN);
printk("%s: after: mac.raw: %x skb->data: %x\n",
__FUNCTION__, (*pskb)->mac.raw, (*pskb)->data);
/* Move the mac addresses to the beginning of the new header. */
memmove((*pskb)->data, (*pskb)->data + VLAN_HLEN, 12);
/* first, the ethernet type */
/* put_unaligned(__constant_htons(ETH_P_8021Q), &veth->h_vlan_proto); */
veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
/* Now, construct the second two bytes. This field looks something
* like:
* usr_priority: 3 bits (high bits)
* CFI 1 bit
* VLAN ID 12 bits (low bits)
*/
veth_TCI = info->vid;
veth_TCI |= 0;
veth->h_vlan_TCI = htons(veth_TCI);
return info->target;
How do I fix the mismatch between skb->mac.raw and skb->data? I was thinking of putting this in the OUTPUT chain instead of postrouting...
Thanks,
Ashwin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \|/ ____ \|/
Ashwin Kashyap @~/ ,. \~@
Intern /_( \__/ )_\
Thomson - Corporate Research \__U_/
(609) 987-7334 Don't Panic!