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!
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.