@ -433,11 +433,12 @@ err:
* @ orig_node : final destination of the created fragments
* @ orig_node : final destination of the created fragments
* @ neigh_node : next - hop of the created fragments
* @ neigh_node : next - hop of the created fragments
*
*
* Return : true on success , false otherwise .
* Return : the netdev tx status or - 1 in case of error .
* When - 1 is returned the skb is not consumed .
*/
*/
bool batadv_frag_send_packet ( struct sk_buff * skb ,
int batadv_frag_send_packet ( struct sk_buff * skb ,
struct batadv_orig_node * orig_node ,
struct batadv_orig_node * orig_node ,
struct batadv_neigh_node * neigh_node )
struct batadv_neigh_node * neigh_node )
{
{
struct batadv_priv * bat_priv ;
struct batadv_priv * bat_priv ;
struct batadv_hard_iface * primary_if = NULL ;
struct batadv_hard_iface * primary_if = NULL ;
@ -446,7 +447,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
unsigned int mtu = neigh_node - > if_incoming - > net_dev - > mtu ;
unsigned int mtu = neigh_node - > if_incoming - > net_dev - > mtu ;
unsigned int header_size = sizeof ( frag_header ) ;
unsigned int header_size = sizeof ( frag_header ) ;
unsigned int max_fragment_size , max_packet_size ;
unsigned int max_fragment_size , max_packet_size ;
bool ret = false ;
int ret = - 1 ;
/* To avoid merge and refragmentation at next-hops we never send
/* To avoid merge and refragmentation at next-hops we never send
* fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
* fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@ -457,12 +458,12 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
/* Don't even try to fragment, if we need more than 16 fragments */
/* Don't even try to fragment, if we need more than 16 fragments */
if ( skb - > len > max_packet_size )
if ( skb - > len > max_packet_size )
goto out_err ;
goto out ;
bat_priv = orig_node - > bat_priv ;
bat_priv = orig_node - > bat_priv ;
primary_if = batadv_primary_if_get_selected ( bat_priv ) ;
primary_if = batadv_primary_if_get_selected ( bat_priv ) ;
if ( ! primary_if )
if ( ! primary_if )
goto out_err ;
goto out ;
/* Create one header to be copied to all fragments */
/* Create one header to be copied to all fragments */
frag_header . packet_type = BATADV_UNICAST_FRAG ;
frag_header . packet_type = BATADV_UNICAST_FRAG ;
@ -488,23 +489,33 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
while ( skb - > len > max_fragment_size ) {
while ( skb - > len > max_fragment_size ) {
skb_fragment = batadv_frag_create ( skb , & frag_header , mtu ) ;
skb_fragment = batadv_frag_create ( skb , & frag_header , mtu ) ;
if ( ! skb_fragment )
if ( ! skb_fragment )
goto out_err ;
goto out ;
batadv_inc_counter ( bat_priv , BATADV_CNT_FRAG_TX ) ;
batadv_inc_counter ( bat_priv , BATADV_CNT_FRAG_TX ) ;
batadv_add_counter ( bat_priv , BATADV_CNT_FRAG_TX_BYTES ,
batadv_add_counter ( bat_priv , BATADV_CNT_FRAG_TX_BYTES ,
skb_fragment - > len + ETH_HLEN ) ;
skb_fragment - > len + ETH_HLEN ) ;
batadv_send_unicast_skb ( skb_fragment , neigh_node ) ;
ret = batadv_send_unicast_skb ( skb_fragment , neigh_node ) ;
if ( ret ! = NET_XMIT_SUCCESS ) {
/* return -1 so that the caller can free the original
* skb
*/
ret = - 1 ;
goto out ;
}
frag_header . no + + ;
frag_header . no + + ;
/* The initial check in this function should cover this case */
/* The initial check in this function should cover this case */
if ( frag_header . no = = BATADV_FRAG_MAX_FRAGMENTS - 1 )
if ( frag_header . no = = BATADV_FRAG_MAX_FRAGMENTS - 1 ) {
goto out_err ;
ret = - 1 ;
goto out ;
}
}
}
/* Make room for the fragment header. */
/* Make room for the fragment header. */
if ( batadv_skb_head_push ( skb , header_size ) < 0 | |
if ( batadv_skb_head_push ( skb , header_size ) < 0 | |
pskb_expand_head ( skb , header_size + ETH_HLEN , 0 , GFP_ATOMIC ) < 0 )
pskb_expand_head ( skb , header_size + ETH_HLEN , 0 , GFP_ATOMIC ) < 0 )
goto out_err ;
goto out ;
memcpy ( skb - > data , & frag_header , header_size ) ;
memcpy ( skb - > data , & frag_header , header_size ) ;
@ -512,11 +523,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
batadv_inc_counter ( bat_priv , BATADV_CNT_FRAG_TX ) ;
batadv_inc_counter ( bat_priv , BATADV_CNT_FRAG_TX ) ;
batadv_add_counter ( bat_priv , BATADV_CNT_FRAG_TX_BYTES ,
batadv_add_counter ( bat_priv , BATADV_CNT_FRAG_TX_BYTES ,
skb - > len + ETH_HLEN ) ;
skb - > len + ETH_HLEN ) ;
batadv_send_unicast_skb ( skb , neigh_node ) ;
ret = batadv_send_unicast_skb ( skb , neigh_node ) ;
ret = true ;
out :
out_err :
if ( primary_if )
if ( primary_if )
batadv_hardif_put ( primary_if ) ;
batadv_hardif_put ( primary_if ) ;