diff options
Diffstat (limited to 'net/batman-adv/fragmentation.c')
| -rw-r--r-- | net/batman-adv/fragmentation.c | 20 | 
1 files changed, 13 insertions, 7 deletions
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 11a23fd6e1a0..8f964beaac28 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -404,7 +404,7 @@ out:   * batadv_frag_create - create a fragment from skb   * @skb: skb to create fragment from   * @frag_head: header to use in new fragment - * @mtu: size of new fragment + * @fragment_size: size of new fragment   *   * Split the passed skb into two fragments: A new one with size matching the   * passed mtu and the old one with the rest. The new skb contains data from the @@ -414,11 +414,11 @@ out:   */  static struct sk_buff *batadv_frag_create(struct sk_buff *skb,  					  struct batadv_frag_packet *frag_head, -					  unsigned int mtu) +					  unsigned int fragment_size)  {  	struct sk_buff *skb_fragment;  	unsigned int header_size = sizeof(*frag_head); -	unsigned int fragment_size = mtu - header_size; +	unsigned int mtu = fragment_size + header_size;  	skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN);  	if (!skb_fragment) @@ -456,7 +456,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,  	struct sk_buff *skb_fragment;  	unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;  	unsigned int header_size = sizeof(frag_header); -	unsigned int max_fragment_size, max_packet_size; +	unsigned int max_fragment_size, num_fragments;  	int ret;  	/* To avoid merge and refragmentation at next-hops we never send @@ -464,10 +464,15 @@ int batadv_frag_send_packet(struct sk_buff *skb,  	 */  	mtu = min_t(unsigned int, mtu, BATADV_FRAG_MAX_FRAG_SIZE);  	max_fragment_size = mtu - header_size; -	max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; + +	if (skb->len == 0 || max_fragment_size == 0) +		return -EINVAL; + +	num_fragments = (skb->len - 1) / max_fragment_size + 1; +	max_fragment_size = (skb->len - 1) / num_fragments + 1;  	/* Don't even try to fragment, if we need more than 16 fragments */ -	if (skb->len > max_packet_size) { +	if (num_fragments > BATADV_FRAG_MAX_FRAGMENTS) {  		ret = -EAGAIN;  		goto free_skb;  	} @@ -507,7 +512,8 @@ int batadv_frag_send_packet(struct sk_buff *skb,  			goto put_primary_if;  		} -		skb_fragment = batadv_frag_create(skb, &frag_header, mtu); +		skb_fragment = batadv_frag_create(skb, &frag_header, +						  max_fragment_size);  		if (!skb_fragment) {  			ret = -ENOMEM;  			goto put_primary_if;  | 
