• Home
  • Raw
  • Download

Lines Matching +full:buffered +full:- +full:negative

1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2013-2020 B.A.T.M.A.N. contributors:
26 #include "hard-interface.h"
30 #include "soft-interface.h"
33 * batadv_frag_clear_chain() - delete entries in the fragment buffer chain
45 hlist_del(&entry->list); in batadv_frag_clear_chain()
48 kfree_skb(entry->skb); in batadv_frag_clear_chain()
50 consume_skb(entry->skb); in batadv_frag_clear_chain()
57 * batadv_frag_purge_orig() - free fragments associated to an orig
68 chain = &orig_node->fragments[i]; in batadv_frag_purge_orig()
69 spin_lock_bh(&chain->lock); in batadv_frag_purge_orig()
72 batadv_frag_clear_chain(&chain->fragment_list, true); in batadv_frag_purge_orig()
73 chain->size = 0; in batadv_frag_purge_orig()
76 spin_unlock_bh(&chain->lock); in batadv_frag_purge_orig()
81 * batadv_frag_size_limit() - maximum possible size of packet to be fragmented
89 limit -= sizeof(struct batadv_frag_packet); in batadv_frag_size_limit()
96 * batadv_frag_init_chain() - check and prepare fragment chain for new fragment
103 * Caller must hold chain->lock.
111 lockdep_assert_held(&chain->lock); in batadv_frag_init_chain()
113 if (chain->seqno == seqno) in batadv_frag_init_chain()
116 if (!hlist_empty(&chain->fragment_list)) in batadv_frag_init_chain()
117 batadv_frag_clear_chain(&chain->fragment_list, true); in batadv_frag_init_chain()
119 chain->size = 0; in batadv_frag_init_chain()
120 chain->seqno = seqno; in batadv_frag_init_chain()
126 * batadv_frag_insert_packet() - insert a fragment into a fragment chain
134 * Return: true if skb is buffered, false on error. If the chain has all the
151 * the later merge. Non-linear merge should be added to remove this in batadv_frag_insert_packet()
157 frag_packet = (struct batadv_frag_packet *)skb->data; in batadv_frag_insert_packet()
158 seqno = ntohs(frag_packet->seqno); in batadv_frag_insert_packet()
165 frag_entry_new->skb = skb; in batadv_frag_insert_packet()
166 frag_entry_new->no = frag_packet->no; in batadv_frag_insert_packet()
172 chain = &orig_node->fragments[bucket]; in batadv_frag_insert_packet()
173 spin_lock_bh(&chain->lock); in batadv_frag_insert_packet()
175 hlist_add_head(&frag_entry_new->list, &chain->fragment_list); in batadv_frag_insert_packet()
176 chain->size = skb->len - hdr_size; in batadv_frag_insert_packet()
177 chain->timestamp = jiffies; in batadv_frag_insert_packet()
178 chain->total_size = ntohs(frag_packet->total_size); in batadv_frag_insert_packet()
184 hlist_for_each_entry(frag_entry_curr, &chain->fragment_list, list) { in batadv_frag_insert_packet()
186 if (frag_entry_curr->no == frag_entry_new->no) in batadv_frag_insert_packet()
190 if (frag_entry_curr->no < frag_entry_new->no) { in batadv_frag_insert_packet()
191 hlist_add_before(&frag_entry_new->list, in batadv_frag_insert_packet()
192 &frag_entry_curr->list); in batadv_frag_insert_packet()
193 chain->size += skb->len - hdr_size; in batadv_frag_insert_packet()
194 chain->timestamp = jiffies; in batadv_frag_insert_packet()
205 hlist_add_behind(&frag_entry_new->list, &frag_entry_last->list); in batadv_frag_insert_packet()
206 chain->size += skb->len - hdr_size; in batadv_frag_insert_packet()
207 chain->timestamp = jiffies; in batadv_frag_insert_packet()
212 if (chain->size > batadv_frag_size_limit() || in batadv_frag_insert_packet()
213 chain->total_size != ntohs(frag_packet->total_size) || in batadv_frag_insert_packet()
214 chain->total_size > batadv_frag_size_limit()) { in batadv_frag_insert_packet()
219 batadv_frag_clear_chain(&chain->fragment_list, true); in batadv_frag_insert_packet()
220 chain->size = 0; in batadv_frag_insert_packet()
221 } else if (ntohs(frag_packet->total_size) == chain->size) { in batadv_frag_insert_packet()
223 hlist_move_list(&chain->fragment_list, chain_out); in batadv_frag_insert_packet()
224 chain->size = 0; in batadv_frag_insert_packet()
228 spin_unlock_bh(&chain->lock); in batadv_frag_insert_packet()
240 * batadv_frag_merge_packets() - merge a chain of fragments
260 entry = hlist_entry(chain->first, struct batadv_frag_list_entry, list); in batadv_frag_merge_packets()
261 hlist_del(&entry->list); in batadv_frag_merge_packets()
262 skb_out = entry->skb; in batadv_frag_merge_packets()
265 packet = (struct batadv_frag_packet *)skb_out->data; in batadv_frag_merge_packets()
266 size = ntohs(packet->total_size) + hdr_size; in batadv_frag_merge_packets()
269 if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { in batadv_frag_merge_packets()
280 skb_out->ip_summed = CHECKSUM_NONE; in batadv_frag_merge_packets()
281 memmove(skb_out->data - ETH_HLEN, skb_mac_header(skb_out), ETH_HLEN); in batadv_frag_merge_packets()
282 skb_set_mac_header(skb_out, -ETH_HLEN); in batadv_frag_merge_packets()
288 size = entry->skb->len - hdr_size; in batadv_frag_merge_packets()
289 skb_put_data(skb_out, entry->skb->data + hdr_size, size); in batadv_frag_merge_packets()
299 * batadv_frag_skb_buffer() - buffer fragment for later merge
306 * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb
309 * Return: true when the packet is merged or buffered, false when skb is not
339 * batadv_frag_skb_fwd() - forward fragments that would exceed MTU when merged
344 * Look up the next-hop of the fragments payload and check if the merged packet
345 * will exceed the MTU towards the next-hop. If so, the fragment is forwarded
354 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); in batadv_frag_skb_fwd()
361 packet = (struct batadv_frag_packet *)skb->data; in batadv_frag_skb_fwd()
362 orig_node_dst = batadv_orig_hash_find(bat_priv, packet->dest); in batadv_frag_skb_fwd()
373 total_size = ntohs(packet->total_size); in batadv_frag_skb_fwd()
374 if (total_size > neigh_node->if_incoming->net_dev->mtu) { in batadv_frag_skb_fwd()
377 skb->len + ETH_HLEN); in batadv_frag_skb_fwd()
379 packet->ttl--; in batadv_frag_skb_fwd()
393 * batadv_frag_create() - create a fragment from skb
411 unsigned int tailroom = net_dev->needed_tailroom; in batadv_frag_create()
420 skb_fragment->priority = skb->priority; in batadv_frag_create()
422 /* Eat the last mtu-bytes of the skb */ in batadv_frag_create()
424 skb_split(skb, skb_fragment, skb->len - fragment_size); in batadv_frag_create()
428 memcpy(skb_fragment->data, frag_head, header_size); in batadv_frag_create()
435 * batadv_frag_send_packet() - create up to 16 fragments from the passed skb
438 * @neigh_node: next-hop of the created fragments
440 * Return: the netdev tx status or a negative errno code on a failure
446 struct net_device *net_dev = neigh_node->if_incoming->net_dev; in batadv_frag_send_packet()
451 unsigned int mtu = net_dev->mtu; in batadv_frag_send_packet()
456 /* To avoid merge and refragmentation at next-hops we never send in batadv_frag_send_packet()
460 max_fragment_size = mtu - header_size; in batadv_frag_send_packet()
462 if (skb->len == 0 || max_fragment_size == 0) in batadv_frag_send_packet()
463 return -EINVAL; in batadv_frag_send_packet()
465 num_fragments = (skb->len - 1) / max_fragment_size + 1; in batadv_frag_send_packet()
466 max_fragment_size = (skb->len - 1) / num_fragments + 1; in batadv_frag_send_packet()
470 ret = -EAGAIN; in batadv_frag_send_packet()
474 bat_priv = orig_node->bat_priv; in batadv_frag_send_packet()
477 ret = -EINVAL; in batadv_frag_send_packet()
484 * batman-adv fragments were created and submitted to the in batadv_frag_send_packet()
485 * hard-interface in batadv_frag_send_packet()
488 ret = -ENOMEM; in batadv_frag_send_packet()
496 frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno)); in batadv_frag_send_packet()
499 frag_header.total_size = htons(skb->len); in batadv_frag_send_packet()
501 /* skb->priority values from 256->263 are magic values to in batadv_frag_send_packet()
506 if (skb->priority >= 256 && skb->priority <= 263) in batadv_frag_send_packet()
507 frag_header.priority = skb->priority - 256; in batadv_frag_send_packet()
511 ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); in batadv_frag_send_packet()
512 ether_addr_copy(frag_header.dest, orig_node->orig); in batadv_frag_send_packet()
515 while (skb->len > max_fragment_size) { in batadv_frag_send_packet()
517 if (unlikely(frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1)) { in batadv_frag_send_packet()
518 ret = -EINVAL; in batadv_frag_send_packet()
525 ret = -ENOMEM; in batadv_frag_send_packet()
531 skb_fragment->len + ETH_HLEN); in batadv_frag_send_packet()
549 memcpy(skb->data, &frag_header, header_size); in batadv_frag_send_packet()
554 skb->len + ETH_HLEN); in batadv_frag_send_packet()