diff options
Diffstat (limited to 'tools/vnet/vnet-module/etherip.c')
-rw-r--r-- | tools/vnet/vnet-module/etherip.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/tools/vnet/vnet-module/etherip.c b/tools/vnet/vnet-module/etherip.c index 2548d1a80a..3e531c7fbe 100644 --- a/tools/vnet/vnet-module/etherip.c +++ b/tools/vnet/vnet-module/etherip.c @@ -128,9 +128,27 @@ static void etherip_tunnel_close(Tunnel *tunnel){ } +static inline int skb_make_headroom(struct sk_buff **pskb, struct sk_buff *skb, int head_n){ + int err = 0; + dprintf("> skb=%p headroom=%d head_n=%d\n", skb, skb_headroom(skb), head_n); + if(head_n > skb_headroom(skb) || skb_cloned(skb) || skb_shared(skb)){ + // Expand header the way GRE does. + struct sk_buff *new_skb = skb_realloc_headroom(skb, head_n + 16); + if(!new_skb){ + err = -ENOMEM; + goto exit; + } + kfree_skb(skb); + *pskb = new_skb; + } else { + *pskb = skb; + } + exit: + return err; +} + /** Send a packet via an etherip tunnel. - * Adds etherip header, new ip header, new ethernet header around - * ethernet frame. + * Adds etherip header and new ip header around ethernet frame. * * @param tunnel tunnel * @param skb packet @@ -150,7 +168,7 @@ static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){ if(etherip_in_udp){ head_n += vnet_n + udp_n; } - err = skb_make_room(&skb, skb, head_n, 0); + err = skb_make_headroom(&skb, skb, head_n); if(err) goto exit; // Null the pointer as we are pushing a new IP header. @@ -219,6 +237,20 @@ int etherip_tunnel_create(VnetId *vnet, VarpAddr *addr, Tunnel *base, Tunnel **t return Tunnel_create(etherip_tunnel_type, vnet, addr, base, tunnel); } +#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER) +/** We need our own copy of this as it is no longer exported from the bridge module. + */ +static inline void _nf_bridge_save_header(struct sk_buff *skb){ + int header_size = 16; + + // Were using this modified to use h_proto instead of skb->protocol. + if(skb->protocol == htons(ETH_P_8021Q)){ + header_size = 18; + } + memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); +} +#endif + /** Do etherip receive processing. * Strips the etherip header to extract the ethernet frame, sets * the vnet from the header and re-receives the frame. @@ -320,10 +352,9 @@ int etherip_protocol_recv(struct sk_buff *skb){ skb->dst = NULL; nf_reset(skb); #ifdef CONFIG_BRIDGE_NETFILTER - // Stop the eth header being clobbered by nf_bridge_maybe_copy_header(). - // Were using this modified to use h_proto instead of skb->protocol. if(skb->nf_bridge){ - nf_bridge_save_header(skb); + // Stop the eth header being clobbered by nf_bridge_maybe_copy_header(). + _nf_bridge_save_header(skb); } #endif #endif // __KERNEL__ |