Lines Matching +full:send +full:- +full:flush +full:- +full:out +full:- +full:sequence

1 // SPDX-License-Identifier: GPL-2.0
35 #include "hard-interface.h"
40 #include "send.h"
41 #include "translation-table.h"
45 * batadv_v_ogm_orig_get() - retrieve and possibly create an originator node
67 kref_get(&orig_node->refcount); in batadv_v_ogm_orig_get()
68 hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, in batadv_v_ogm_orig_get()
70 &orig_node->hash_entry); in batadv_v_ogm_orig_get()
82 * batadv_v_ogm_start_queue_timer() - restart the OGM aggregation timer
83 * @hard_iface: the interface to use to send the OGM
90 msecs += get_random_u32_below(msecs / 5) - (msecs / 10); in batadv_v_ogm_start_queue_timer()
91 queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.aggr_wq, in batadv_v_ogm_start_queue_timer()
96 * batadv_v_ogm_start_timer() - restart the OGM sending timer
105 if (delayed_work_pending(&bat_priv->bat_v.ogm_wq)) in batadv_v_ogm_start_timer()
108 msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER; in batadv_v_ogm_start_timer()
110 queue_delayed_work(batadv_event_workqueue, &bat_priv->bat_v.ogm_wq, in batadv_v_ogm_start_timer()
115 * batadv_v_ogm_send_to_if() - send a batman ogm using a given interface
116 * @skb: the OGM to send
117 * @hard_iface: the interface to use to send the OGM
122 struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface); in batadv_v_ogm_send_to_if()
124 if (hard_iface->if_status != BATADV_IF_ACTIVE) { in batadv_v_ogm_send_to_if()
131 skb->len + ETH_HLEN); in batadv_v_ogm_send_to_if()
137 * batadv_v_ogm_len() - OGMv2 packet length
147 ogm_packet = (struct batadv_ogm2_packet *)skb->data; in batadv_v_ogm_len()
148 return BATADV_OGM2_HLEN + ntohs(ogm_packet->tvlv_len); in batadv_v_ogm_len()
152 * batadv_v_ogm_queue_left() - check if given OGM still fits aggregation queue
154 * @hard_iface: the interface to use to send the OGM
156 * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
163 unsigned int max = min_t(unsigned int, hard_iface->net_dev->mtu, in batadv_v_ogm_queue_left()
167 lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_queue_left()
169 return hard_iface->bat_v.aggr_len + ogm_len <= max; in batadv_v_ogm_queue_left()
173 * batadv_v_ogm_aggr_list_free - free all elements in an aggregation queue
178 * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
182 lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_aggr_list_free()
184 __skb_queue_purge(&hard_iface->bat_v.aggr_list); in batadv_v_ogm_aggr_list_free()
185 hard_iface->bat_v.aggr_len = 0; in batadv_v_ogm_aggr_list_free()
189 * batadv_v_ogm_aggr_send() - flush & send aggregation queue
190 * @hard_iface: the interface with the aggregation queue to flush
197 * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
201 unsigned int aggr_len = hard_iface->bat_v.aggr_len; in batadv_v_ogm_aggr_send()
206 lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_aggr_send()
220 while ((skb = __skb_dequeue(&hard_iface->bat_v.aggr_list))) { in batadv_v_ogm_aggr_send()
221 hard_iface->bat_v.aggr_len -= batadv_v_ogm_len(skb); in batadv_v_ogm_aggr_send()
224 skb_put_data(skb_aggr, skb->data, ogm_len); in batadv_v_ogm_aggr_send()
233 * batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface
240 struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface); in batadv_v_ogm_queue_on_if()
242 if (!atomic_read(&bat_priv->aggregated_ogms)) { in batadv_v_ogm_queue_on_if()
247 spin_lock_bh(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_queue_on_if()
251 hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb); in batadv_v_ogm_queue_on_if()
252 __skb_queue_tail(&hard_iface->bat_v.aggr_list, skb); in batadv_v_ogm_queue_on_if()
253 spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_queue_on_if()
257 * batadv_v_ogm_send_meshif() - periodic worker broadcasting the own OGM
271 lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_send_meshif()
273 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) in batadv_v_ogm_send_meshif()
274 goto out; in batadv_v_ogm_send_meshif()
276 ogm_buff = bat_priv->bat_v.ogm_buff; in batadv_v_ogm_send_meshif()
277 ogm_buff_len = bat_priv->bat_v.ogm_buff_len; in batadv_v_ogm_send_meshif()
286 bat_priv->bat_v.ogm_buff = ogm_buff; in batadv_v_ogm_send_meshif()
287 bat_priv->bat_v.ogm_buff_len = ogm_buff_len; in batadv_v_ogm_send_meshif()
296 ogm_packet = (struct batadv_ogm2_packet *)skb->data; in batadv_v_ogm_send_meshif()
297 ogm_packet->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno)); in batadv_v_ogm_send_meshif()
298 atomic_inc(&bat_priv->bat_v.ogm_seqno); in batadv_v_ogm_send_meshif()
299 ogm_packet->tvlv_len = htons(tvlv_len); in batadv_v_ogm_send_meshif()
303 netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) { in batadv_v_ogm_send_meshif()
304 if (!kref_get_unless_zero(&hard_iface->refcount)) in batadv_v_ogm_send_meshif()
326 hard_iface->net_dev->name, type); in batadv_v_ogm_send_meshif()
334 ogm_packet->orig, ntohl(ogm_packet->seqno), in batadv_v_ogm_send_meshif()
335 ntohl(ogm_packet->throughput), ogm_packet->ttl, in batadv_v_ogm_send_meshif()
336 hard_iface->net_dev->name, in batadv_v_ogm_send_meshif()
337 hard_iface->net_dev->dev_addr); in batadv_v_ogm_send_meshif()
355 out: in batadv_v_ogm_send_meshif()
360 * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
371 mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_send()
373 mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_send()
377 * batadv_v_ogm_aggr_work() - OGM queue periodic task per interface
390 spin_lock_bh(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_aggr_work()
392 spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_aggr_work()
398 * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V
407 struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface); in batadv_v_ogm_iface_enable()
416 * batadv_v_ogm_iface_disable() - release OGM interface private resources
421 cancel_delayed_work_sync(&hard_iface->bat_v.aggr_wq); in batadv_v_ogm_iface_disable()
423 spin_lock_bh(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_iface_disable()
425 spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock); in batadv_v_ogm_iface_disable()
429 * batadv_v_ogm_primary_iface_set() - set a new primary interface
434 struct batadv_priv *bat_priv = netdev_priv(primary_iface->mesh_iface); in batadv_v_ogm_primary_iface_set()
437 mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_primary_iface_set()
438 if (!bat_priv->bat_v.ogm_buff) in batadv_v_ogm_primary_iface_set()
441 ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff; in batadv_v_ogm_primary_iface_set()
442 ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr); in batadv_v_ogm_primary_iface_set()
445 mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_primary_iface_set()
449 * batadv_v_forward_penalty() - apply a penalty to the throughput metric
461 * - throughput * 50% if the incoming and outgoing interface are the
464 * - throughput if the outgoing interface is the default
467 * - throughput * node hop penalty otherwise
476 int if_hop_penalty = atomic_read(&if_incoming->hop_penalty); in batadv_v_forward_penalty()
477 int hop_penalty = atomic_read(&bat_priv->hop_penalty); in batadv_v_forward_penalty()
481 throughput = throughput * (hop_penalty_max - if_hop_penalty) / in batadv_v_forward_penalty()
494 !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX)) in batadv_v_forward_penalty()
498 return throughput * (hop_penalty_max - hop_penalty) / hop_penalty_max; in batadv_v_forward_penalty()
502 * batadv_v_ogm_forward() - check conditions and forward an OGM to the given
532 goto out; in batadv_v_ogm_forward()
536 goto out; in batadv_v_ogm_forward()
543 goto out; in batadv_v_ogm_forward()
546 if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm_received->seqno)) in batadv_v_ogm_forward()
547 goto out; in batadv_v_ogm_forward()
549 orig_ifinfo->last_seqno_forwarded = ntohl(ogm_received->seqno); in batadv_v_ogm_forward()
551 if (ogm_received->ttl <= 1) { in batadv_v_ogm_forward()
553 goto out; in batadv_v_ogm_forward()
558 goto out; in batadv_v_ogm_forward()
560 tvlv_len = ntohs(ogm_received->tvlv_len); in batadv_v_ogm_forward()
563 skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev, in batadv_v_ogm_forward()
566 goto out; in batadv_v_ogm_forward()
573 ogm_forward->throughput = htonl(neigh_ifinfo->bat_v.throughput); in batadv_v_ogm_forward()
574 ogm_forward->ttl--; in batadv_v_ogm_forward()
578 if_outgoing->net_dev->name, ntohl(ogm_forward->throughput), in batadv_v_ogm_forward()
579 ogm_forward->ttl, if_incoming->net_dev->name); in batadv_v_ogm_forward()
583 out: in batadv_v_ogm_forward()
590 * batadv_v_ogm_metric_update() - update route metric based on OGM
613 int ret = -EINVAL; in batadv_v_ogm_metric_update()
619 goto out; in batadv_v_ogm_metric_update()
621 seq_diff = ntohl(ogm2->seqno) - orig_ifinfo->last_real_seqno; in batadv_v_ogm_metric_update()
623 if (!hlist_empty(&orig_node->neigh_list) && in batadv_v_ogm_metric_update()
626 &orig_ifinfo->batman_seqno_reset, in batadv_v_ogm_metric_update()
630 ogm2->orig); in batadv_v_ogm_metric_update()
633 orig_ifinfo->batman_seqno_reset, jiffies); in batadv_v_ogm_metric_update()
634 goto out; in batadv_v_ogm_metric_update()
641 goto out; in batadv_v_ogm_metric_update()
643 neigh_node->last_seen = jiffies; in batadv_v_ogm_metric_update()
645 orig_node->last_seen = jiffies; in batadv_v_ogm_metric_update()
647 orig_ifinfo->last_real_seqno = ntohl(ogm2->seqno); in batadv_v_ogm_metric_update()
648 orig_ifinfo->last_ttl = ogm2->ttl; in batadv_v_ogm_metric_update()
652 goto out; in batadv_v_ogm_metric_update()
656 ntohl(ogm2->throughput)); in batadv_v_ogm_metric_update()
657 neigh_ifinfo->bat_v.throughput = path_throughput; in batadv_v_ogm_metric_update()
658 neigh_ifinfo->bat_v.last_seqno = ntohl(ogm2->seqno); in batadv_v_ogm_metric_update()
659 neigh_ifinfo->last_ttl = ogm2->ttl; in batadv_v_ogm_metric_update()
665 out: in batadv_v_ogm_metric_update()
673 * batadv_v_ogm_route_update() - update routes based on OGM
702 orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source); in batadv_v_ogm_route_update()
704 goto out; in batadv_v_ogm_route_update()
713 if (router && router->orig_node != orig_node && !orig_neigh_router) { in batadv_v_ogm_route_update()
716 goto out; in batadv_v_ogm_route_update()
731 goto out; in batadv_v_ogm_route_update()
743 goto out; in batadv_v_ogm_route_update()
745 neigh_last_seqno = neigh_ifinfo->bat_v.last_seqno; in batadv_v_ogm_route_update()
746 router_last_seqno = router_ifinfo->bat_v.last_seqno; in batadv_v_ogm_route_update()
747 neigh_seq_diff = neigh_last_seqno - router_last_seqno; in batadv_v_ogm_route_update()
748 router_throughput = router_ifinfo->bat_v.throughput; in batadv_v_ogm_route_update()
749 neigh_throughput = neigh_ifinfo->bat_v.throughput; in batadv_v_ogm_route_update()
753 goto out; in batadv_v_ogm_route_update()
757 out: in batadv_v_ogm_route_update()
768 * batadv_v_ogm_process_per_outif() - process a batman v OGM for an outgoing if
794 /* outdated sequence numbers are to be discarded */ in batadv_v_ogm_process_per_outif()
803 ntohs(ogm2->tvlv_len)); in batadv_v_ogm_process_per_outif()
817 * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
836 next_buff_pos += ntohs(ogm2_packet->tvlv_len); in batadv_v_ogm_aggr_packet()
842 * batadv_v_ogm_process() - process an incoming batman v OGM
850 struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface); in batadv_v_ogm_process()
862 ogm_packet = (struct batadv_ogm2_packet *)(skb->data + ogm_offset); in batadv_v_ogm_process()
864 ogm_throughput = ntohl(ogm_packet->throughput); in batadv_v_ogm_process()
868 ethhdr->h_source, if_incoming->net_dev->name, in batadv_v_ogm_process()
869 if_incoming->net_dev->dev_addr, ogm_packet->orig, in batadv_v_ogm_process()
870 ntohl(ogm_packet->seqno), ogm_throughput, ogm_packet->ttl, in batadv_v_ogm_process()
871 ogm_packet->version, ntohs(ogm_packet->tvlv_len)); in batadv_v_ogm_process()
873 if (batadv_is_my_mac(bat_priv, ogm_packet->orig)) { in batadv_v_ogm_process()
889 hardif_neigh = batadv_hardif_neigh_get(if_incoming, ethhdr->h_source); in batadv_v_ogm_process()
893 goto out; in batadv_v_ogm_process()
896 orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig); in batadv_v_ogm_process()
898 goto out; in batadv_v_ogm_process()
901 ethhdr->h_source); in batadv_v_ogm_process()
903 goto out; in batadv_v_ogm_process()
907 * - If this OGM traveled one hop so far (emitted by single hop in batadv_v_ogm_process()
909 * - For OGMs traversing more than hop the path throughput metric is in batadv_v_ogm_process()
912 link_throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput); in batadv_v_ogm_process()
914 ogm_packet->throughput = htonl(path_throughput); in batadv_v_ogm_process()
921 netdev_for_each_lower_private_rcu(bat_priv->mesh_iface, hard_iface, iter) { in batadv_v_ogm_process()
922 if (hard_iface->if_status != BATADV_IF_ACTIVE) in batadv_v_ogm_process()
925 if (!kref_get_unless_zero(&hard_iface->refcount)) in batadv_v_ogm_process()
929 ogm_packet->orig, in batadv_v_ogm_process()
930 hardif_neigh->orig); in batadv_v_ogm_process()
950 ogm_packet->orig, hard_iface->net_dev->name, in batadv_v_ogm_process()
964 out: in batadv_v_ogm_process()
971 * batadv_v_ogm_packet_recv() - OGM2 receiving handler
981 struct batadv_priv *bat_priv = netdev_priv(if_incoming->mesh_iface); in batadv_v_ogm_packet_recv()
991 if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0) in batadv_v_ogm_packet_recv()
998 if (batadv_is_my_mac(bat_priv, ethhdr->h_source)) in batadv_v_ogm_packet_recv()
1003 skb->len + ETH_HLEN); in batadv_v_ogm_packet_recv()
1006 ogm_packet = (struct batadv_ogm2_packet *)skb->data; in batadv_v_ogm_packet_recv()
1013 ogm_offset += ntohs(ogm_packet->tvlv_len); in batadv_v_ogm_packet_recv()
1015 packet_pos = skb->data + ogm_offset; in batadv_v_ogm_packet_recv()
1031 * batadv_v_ogm_init() - initialise the OGM2 engine
1042 bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN; in batadv_v_ogm_init()
1043 ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC); in batadv_v_ogm_init()
1045 return -ENOMEM; in batadv_v_ogm_init()
1047 bat_priv->bat_v.ogm_buff = ogm_buff; in batadv_v_ogm_init()
1049 ogm_packet->packet_type = BATADV_OGM2; in batadv_v_ogm_init()
1050 ogm_packet->version = BATADV_COMPAT_VERSION; in batadv_v_ogm_init()
1051 ogm_packet->ttl = BATADV_TTL; in batadv_v_ogm_init()
1052 ogm_packet->flags = BATADV_NO_FLAGS; in batadv_v_ogm_init()
1053 ogm_packet->throughput = htonl(BATADV_THROUGHPUT_MAX_VALUE); in batadv_v_ogm_init()
1057 atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno); in batadv_v_ogm_init()
1058 INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send); in batadv_v_ogm_init()
1060 mutex_init(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_init()
1066 * batadv_v_ogm_free() - free OGM private resources
1071 cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq); in batadv_v_ogm_free()
1073 mutex_lock(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_free()
1075 kfree(bat_priv->bat_v.ogm_buff); in batadv_v_ogm_free()
1076 bat_priv->bat_v.ogm_buff = NULL; in batadv_v_ogm_free()
1077 bat_priv->bat_v.ogm_buff_len = 0; in batadv_v_ogm_free()
1079 mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex); in batadv_v_ogm_free()