aggregation.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  3. *
  4. * Marek Lindner, Simon Wunderlich
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of version 2 of the GNU General Public
  8. * License as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18. * 02110-1301, USA
  19. *
  20. */
  21. #include "main.h"
  22. #include "translation-table.h"
  23. #include "aggregation.h"
  24. #include "send.h"
  25. #include "routing.h"
  26. #include "hard-interface.h"
  27. /* return true if new_packet can be aggregated with forw_packet */
  28. static bool can_aggregate_with(const struct batman_ogm_packet
  29. *new_batman_ogm_packet,
  30. struct bat_priv *bat_priv,
  31. int packet_len,
  32. unsigned long send_time,
  33. bool directlink,
  34. const struct hard_iface *if_incoming,
  35. const struct forw_packet *forw_packet)
  36. {
  37. struct batman_ogm_packet *batman_ogm_packet =
  38. (struct batman_ogm_packet *)forw_packet->skb->data;
  39. int aggregated_bytes = forw_packet->packet_len + packet_len;
  40. struct hard_iface *primary_if = NULL;
  41. bool res = false;
  42. /**
  43. * we can aggregate the current packet to this aggregated packet
  44. * if:
  45. *
  46. * - the send time is within our MAX_AGGREGATION_MS time
  47. * - the resulting packet wont be bigger than
  48. * MAX_AGGREGATION_BYTES
  49. */
  50. if (time_before(send_time, forw_packet->send_time) &&
  51. time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
  52. forw_packet->send_time) &&
  53. (aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
  54. /**
  55. * check aggregation compatibility
  56. * -> direct link packets are broadcasted on
  57. * their interface only
  58. * -> aggregate packet if the current packet is
  59. * a "global" packet as well as the base
  60. * packet
  61. */
  62. primary_if = primary_if_get_selected(bat_priv);
  63. if (!primary_if)
  64. goto out;
  65. /* packets without direct link flag and high TTL
  66. * are flooded through the net */
  67. if ((!directlink) &&
  68. (!(batman_ogm_packet->flags & DIRECTLINK)) &&
  69. (batman_ogm_packet->ttl != 1) &&
  70. /* own packets originating non-primary
  71. * interfaces leave only that interface */
  72. ((!forw_packet->own) ||
  73. (forw_packet->if_incoming == primary_if))) {
  74. res = true;
  75. goto out;
  76. }
  77. /* if the incoming packet is sent via this one
  78. * interface only - we still can aggregate */
  79. if ((directlink) &&
  80. (new_batman_ogm_packet->ttl == 1) &&
  81. (forw_packet->if_incoming == if_incoming) &&
  82. /* packets from direct neighbors or
  83. * own secondary interface packets
  84. * (= secondary interface packets in general) */
  85. (batman_ogm_packet->flags & DIRECTLINK ||
  86. (forw_packet->own &&
  87. forw_packet->if_incoming != primary_if))) {
  88. res = true;
  89. goto out;
  90. }
  91. }
  92. out:
  93. if (primary_if)
  94. hardif_free_ref(primary_if);
  95. return res;
  96. }
  97. /* create a new aggregated packet and add this packet to it */
  98. static void new_aggregated_packet(const unsigned char *packet_buff,
  99. int packet_len, unsigned long send_time,
  100. bool direct_link,
  101. struct hard_iface *if_incoming,
  102. int own_packet)
  103. {
  104. struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
  105. struct forw_packet *forw_packet_aggr;
  106. unsigned char *skb_buff;
  107. if (!atomic_inc_not_zero(&if_incoming->refcount))
  108. return;
  109. /* own packet should always be scheduled */
  110. if (!own_packet) {
  111. if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) {
  112. bat_dbg(DBG_BATMAN, bat_priv,
  113. "batman packet queue full\n");
  114. goto out;
  115. }
  116. }
  117. forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC);
  118. if (!forw_packet_aggr) {
  119. if (!own_packet)
  120. atomic_inc(&bat_priv->batman_queue_left);
  121. goto out;
  122. }
  123. if ((atomic_read(&bat_priv->aggregated_ogms)) &&
  124. (packet_len < MAX_AGGREGATION_BYTES))
  125. forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES +
  126. sizeof(struct ethhdr));
  127. else
  128. forw_packet_aggr->skb = dev_alloc_skb(packet_len +
  129. sizeof(struct ethhdr));
  130. if (!forw_packet_aggr->skb) {
  131. if (!own_packet)
  132. atomic_inc(&bat_priv->batman_queue_left);
  133. kfree(forw_packet_aggr);
  134. goto out;
  135. }
  136. skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr));
  137. INIT_HLIST_NODE(&forw_packet_aggr->list);
  138. skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
  139. forw_packet_aggr->packet_len = packet_len;
  140. memcpy(skb_buff, packet_buff, packet_len);
  141. forw_packet_aggr->own = own_packet;
  142. forw_packet_aggr->if_incoming = if_incoming;
  143. forw_packet_aggr->num_packets = 0;
  144. forw_packet_aggr->direct_link_flags = NO_FLAGS;
  145. forw_packet_aggr->send_time = send_time;
  146. /* save packet direct link flag status */
  147. if (direct_link)
  148. forw_packet_aggr->direct_link_flags |= 1;
  149. /* add new packet to packet list */
  150. spin_lock_bh(&bat_priv->forw_bat_list_lock);
  151. hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
  152. spin_unlock_bh(&bat_priv->forw_bat_list_lock);
  153. /* start timer for this packet */
  154. INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
  155. send_outstanding_bat_packet);
  156. queue_delayed_work(bat_event_workqueue,
  157. &forw_packet_aggr->delayed_work,
  158. send_time - jiffies);
  159. return;
  160. out:
  161. hardif_free_ref(if_incoming);
  162. }
  163. /* aggregate a new packet into the existing aggregation */
  164. static void aggregate(struct forw_packet *forw_packet_aggr,
  165. const unsigned char *packet_buff, int packet_len,
  166. bool direct_link)
  167. {
  168. unsigned char *skb_buff;
  169. skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
  170. memcpy(skb_buff, packet_buff, packet_len);
  171. forw_packet_aggr->packet_len += packet_len;
  172. forw_packet_aggr->num_packets++;
  173. /* save packet direct link flag status */
  174. if (direct_link)
  175. forw_packet_aggr->direct_link_flags |=
  176. (1 << forw_packet_aggr->num_packets);
  177. }
  178. void add_bat_packet_to_list(struct bat_priv *bat_priv,
  179. unsigned char *packet_buff, int packet_len,
  180. struct hard_iface *if_incoming, int own_packet,
  181. unsigned long send_time)
  182. {
  183. /**
  184. * _aggr -> pointer to the packet we want to aggregate with
  185. * _pos -> pointer to the position in the queue
  186. */
  187. struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL;
  188. struct hlist_node *tmp_node;
  189. struct batman_ogm_packet *batman_ogm_packet;
  190. bool direct_link;
  191. batman_ogm_packet = (struct batman_ogm_packet *)packet_buff;
  192. direct_link = batman_ogm_packet->flags & DIRECTLINK ? 1 : 0;
  193. /* find position for the packet in the forward queue */
  194. spin_lock_bh(&bat_priv->forw_bat_list_lock);
  195. /* own packets are not to be aggregated */
  196. if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) {
  197. hlist_for_each_entry(forw_packet_pos, tmp_node,
  198. &bat_priv->forw_bat_list, list) {
  199. if (can_aggregate_with(batman_ogm_packet,
  200. bat_priv,
  201. packet_len,
  202. send_time,
  203. direct_link,
  204. if_incoming,
  205. forw_packet_pos)) {
  206. forw_packet_aggr = forw_packet_pos;
  207. break;
  208. }
  209. }
  210. }
  211. /* nothing to aggregate with - either aggregation disabled or no
  212. * suitable aggregation packet found */
  213. if (!forw_packet_aggr) {
  214. /* the following section can run without the lock */
  215. spin_unlock_bh(&bat_priv->forw_bat_list_lock);
  216. /**
  217. * if we could not aggregate this packet with one of the others
  218. * we hold it back for a while, so that it might be aggregated
  219. * later on
  220. */
  221. if ((!own_packet) &&
  222. (atomic_read(&bat_priv->aggregated_ogms)))
  223. send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
  224. new_aggregated_packet(packet_buff, packet_len,
  225. send_time, direct_link,
  226. if_incoming, own_packet);
  227. } else {
  228. aggregate(forw_packet_aggr,
  229. packet_buff, packet_len,
  230. direct_link);
  231. spin_unlock_bh(&bat_priv->forw_bat_list_lock);
  232. }
  233. }