Using eth_hdr() instead of skb->data avoids some ugly type casts.
I wasn't able to reproduce the skb ether header pointer mismatch mentioned in batadv_bla_tx() on a 3.11 kernel with a vlan on top of bat0 and therefore removed the according skb_reset_mac_header() call, too. Nevertheless I've added a check to the beginning of batadv_interface_tx() as I guess there might potentially be some device drivers not being that nice.
Signed-off-by: Linus Lüssing linus.luessing@web.de --- v2: added missing type cast
bridge_loop_avoidance.c | 3 --- soft-interface.c | 12 +++++++++--- 2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c index 5c0eda4..26ec489 100644 --- a/bridge_loop_avoidance.c +++ b/bridge_loop_avoidance.c @@ -1535,9 +1535,6 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, if (!atomic_read(&bat_priv->bridge_loop_avoidance)) goto allow;
- /* in VLAN case, the mac header might not be set. */ - skb_reset_mac_header(skb); - if (batadv_bla_process_claim(bat_priv, primary_if, skb)) goto handled;
diff --git a/soft-interface.c b/soft-interface.c index f82c267..fd7af1c 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -176,7 +176,13 @@ static int batadv_interface_tx(struct sk_buff *skb,
soft_iface->trans_start = jiffies; vid = batadv_get_vid(skb, 0); - ethhdr = (struct ethhdr *)skb->data; + + if ((struct ethhdr *)skb->data != eth_hdr(skb)) { + pr_warn("Upper device did not set the ethernet header pointer correctly - adjusting\n"); + skb_reset_mac_header(skb); + } + + ethhdr = eth_hdr(skb);
switch (ntohs(ethhdr->h_proto)) { case ETH_P_8021Q: @@ -194,7 +200,7 @@ static int batadv_interface_tx(struct sk_buff *skb, goto dropped;
/* skb->data might have been reallocated by batadv_bla_tx() */ - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb);
/* Register the client MAC in the transtable */ if (!is_multicast_ether_addr(ethhdr->h_source)) { @@ -230,7 +236,7 @@ static int batadv_interface_tx(struct sk_buff *skb, /* skb->data may have been modified by * batadv_gw_dhcp_recipient_get() */ - ethhdr = (struct ethhdr *)skb->data; + ethhdr = eth_hdr(skb); /* if gw_mode is on, broadcast any non-DHCP message. * All the DHCP packets are going to be sent as unicast */
On Thursday 16 January 2014 01:39:21 Linus Lüssing wrote:
if ((struct ethhdr *)skb->data != eth_hdr(skb)) {
pr_warn("Upper device did not set the ethernet header
pointer correctly - adjusting\n");
skb_reset_mac_header(skb);
}
How about using ratelimit or else we end up with many log messages ?
Cheers, Marek
Hi Linus!
On 16/01/14 01:39, Linus Lüssing wrote:
- if ((struct ethhdr *)skb->data != eth_hdr(skb)) {
pr_warn("Upper device did not set the ethernet header pointer correctly - adjusting\n");
skb_reset_mac_header(skb);
- }
I think that if we really want to properly set the mac_header we should just do it and forget about the if and about the warning.
It's a really "stupid" operation and in the end we have many spots in the kernel where the pointers are just set without adding too much overhead like messages or other things...
Cheers,
b.a.t.m.a.n@lists.open-mesh.org