From 4451b27f8f5d49f6e70ea2bd7f5c6648f0fad189 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 25 Jan 2011 22:02:31 +0000 Subject: [PATCH] --- yaml --- r: 236822 b: refs/heads/master c: ae361ce19fa135035c6b83ac1f07090b72fd4b8f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/batman-adv/packet.h | 1 + trunk/net/batman-adv/routing.c | 2 +- trunk/net/batman-adv/unicast.c | 8 ++++++-- trunk/net/batman-adv/unicast.h | 23 +++++++++++++++++++++++ 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 0b07cfcc260b..e3e44d5398cf 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5c77d8bb8aeb4ec6804b6c32061109ba2ea6988d +refs/heads/master: ae361ce19fa135035c6b83ac1f07090b72fd4b8f diff --git a/trunk/net/batman-adv/packet.h b/trunk/net/batman-adv/packet.h index 2284e8129cb2..03ce0d314c9e 100644 --- a/trunk/net/batman-adv/packet.h +++ b/trunk/net/batman-adv/packet.h @@ -50,6 +50,7 @@ /* fragmentation defines */ #define UNI_FRAG_HEAD 0x01 +#define UNI_FRAG_LARGETAIL 0x02 struct batman_packet { uint8_t packet_type; diff --git a/trunk/net/batman-adv/routing.c b/trunk/net/batman-adv/routing.c index 8828eddd3f72..a8cd3897b7d0 100644 --- a/trunk/net/batman-adv/routing.c +++ b/trunk/net/batman-adv/routing.c @@ -1193,7 +1193,7 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, dstaddr); if (unicast_packet->packet_type == BAT_UNICAST_FRAG && - 2 * skb->len - hdr_size <= batman_if->net_dev->mtu) { + frag_can_reassemble(skb, batman_if->net_dev->mtu)) { ret = frag_reassemble_skb(skb, bat_priv, &new_skb); diff --git a/trunk/net/batman-adv/unicast.c b/trunk/net/batman-adv/unicast.c index 811f7fc7932d..fc77079b18bb 100644 --- a/trunk/net/batman-adv/unicast.c +++ b/trunk/net/batman-adv/unicast.c @@ -225,6 +225,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, int uc_hdr_len = sizeof(struct unicast_packet); int ucf_hdr_len = sizeof(struct unicast_frag_packet); int data_len = skb->len - uc_hdr_len; + int large_tail = 0; if (!bat_priv->primary_if) goto dropped; @@ -254,8 +255,11 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); - frag1->flags |= UNI_FRAG_HEAD; - frag2->flags &= ~UNI_FRAG_HEAD; + if (data_len & 1) + large_tail = UNI_FRAG_LARGETAIL; + + frag1->flags = UNI_FRAG_HEAD | large_tail; + frag2->flags = large_tail; frag1->seqno = htons((uint16_t)atomic_inc_return( &batman_if->frag_seqno)); diff --git a/trunk/net/batman-adv/unicast.h b/trunk/net/batman-adv/unicast.h index e32b7867a9a4..e7211c279201 100644 --- a/trunk/net/batman-adv/unicast.h +++ b/trunk/net/batman-adv/unicast.h @@ -22,6 +22,8 @@ #ifndef _NET_BATMAN_ADV_UNICAST_H_ #define _NET_BATMAN_ADV_UNICAST_H_ +#include "packet.h" + #define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */ #define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ @@ -32,4 +34,25 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv); int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, struct batman_if *batman_if, uint8_t dstaddr[]); +static inline int frag_can_reassemble(struct sk_buff *skb, int mtu) +{ + struct unicast_frag_packet *unicast_packet; + int uneven_correction = 0; + unsigned int merged_size; + + unicast_packet = (struct unicast_frag_packet *)skb->data; + + if (unicast_packet->flags & UNI_FRAG_LARGETAIL) { + if (unicast_packet->flags & UNI_FRAG_HEAD) + uneven_correction = 1; + else + uneven_correction = -1; + } + + merged_size = (skb->len - sizeof(struct unicast_frag_packet)) * 2; + merged_size += sizeof(struct unicast_packet) + uneven_correction; + + return merged_size <= mtu; +} + #endif /* _NET_BATMAN_ADV_UNICAST_H_ */