bat_iv_ogm.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  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 "bat_ogm.h"
  23. #include "translation-table.h"
  24. #include "ring_buffer.h"
  25. #include "originator.h"
  26. #include "routing.h"
  27. #include "gateway_common.h"
  28. #include "gateway_client.h"
  29. #include "hard-interface.h"
  30. #include "send.h"
  31. void bat_ogm_init(struct hard_iface *hard_iface)
  32. {
  33. struct batman_ogm_packet *batman_ogm_packet;
  34. hard_iface->packet_len = BATMAN_OGM_LEN;
  35. hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
  36. batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
  37. batman_ogm_packet->packet_type = BAT_OGM;
  38. batman_ogm_packet->version = COMPAT_VERSION;
  39. batman_ogm_packet->flags = NO_FLAGS;
  40. batman_ogm_packet->ttl = 2;
  41. batman_ogm_packet->tq = TQ_MAX_VALUE;
  42. batman_ogm_packet->tt_num_changes = 0;
  43. batman_ogm_packet->ttvn = 0;
  44. }
  45. void bat_ogm_init_primary(struct hard_iface *hard_iface)
  46. {
  47. struct batman_ogm_packet *batman_ogm_packet;
  48. batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
  49. batman_ogm_packet->flags = PRIMARIES_FIRST_HOP;
  50. batman_ogm_packet->ttl = TTL;
  51. }
  52. void bat_ogm_update_mac(struct hard_iface *hard_iface)
  53. {
  54. struct batman_ogm_packet *batman_ogm_packet;
  55. batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
  56. memcpy(batman_ogm_packet->orig,
  57. hard_iface->net_dev->dev_addr, ETH_ALEN);
  58. memcpy(batman_ogm_packet->prev_sender,
  59. hard_iface->net_dev->dev_addr, ETH_ALEN);
  60. }
  61. /* is there another aggregated packet here? */
  62. static int bat_ogm_aggr_packet(int buff_pos, int packet_len,
  63. int tt_num_changes)
  64. {
  65. int next_buff_pos = buff_pos + BATMAN_OGM_LEN + tt_len(tt_num_changes);
  66. return (next_buff_pos <= packet_len) &&
  67. (next_buff_pos <= MAX_AGGREGATION_BYTES);
  68. }
  69. static void bat_ogm_orig_update(struct bat_priv *bat_priv,
  70. struct orig_node *orig_node,
  71. const struct ethhdr *ethhdr,
  72. const struct batman_ogm_packet
  73. *batman_ogm_packet,
  74. struct hard_iface *if_incoming,
  75. const unsigned char *tt_buff, int is_duplicate)
  76. {
  77. struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
  78. struct neigh_node *router = NULL;
  79. struct orig_node *orig_node_tmp;
  80. struct hlist_node *node;
  81. uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
  82. bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
  83. "Searching and updating originator entry of received packet\n");
  84. rcu_read_lock();
  85. hlist_for_each_entry_rcu(tmp_neigh_node, node,
  86. &orig_node->neigh_list, list) {
  87. if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
  88. (tmp_neigh_node->if_incoming == if_incoming) &&
  89. atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
  90. if (neigh_node)
  91. neigh_node_free_ref(neigh_node);
  92. neigh_node = tmp_neigh_node;
  93. continue;
  94. }
  95. if (is_duplicate)
  96. continue;
  97. spin_lock_bh(&tmp_neigh_node->tq_lock);
  98. ring_buffer_set(tmp_neigh_node->tq_recv,
  99. &tmp_neigh_node->tq_index, 0);
  100. tmp_neigh_node->tq_avg =
  101. ring_buffer_avg(tmp_neigh_node->tq_recv);
  102. spin_unlock_bh(&tmp_neigh_node->tq_lock);
  103. }
  104. if (!neigh_node) {
  105. struct orig_node *orig_tmp;
  106. orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
  107. if (!orig_tmp)
  108. goto unlock;
  109. neigh_node = create_neighbor(orig_node, orig_tmp,
  110. ethhdr->h_source, if_incoming);
  111. orig_node_free_ref(orig_tmp);
  112. if (!neigh_node)
  113. goto unlock;
  114. } else
  115. bat_dbg(DBG_BATMAN, bat_priv,
  116. "Updating existing last-hop neighbor of originator\n");
  117. rcu_read_unlock();
  118. orig_node->flags = batman_ogm_packet->flags;
  119. neigh_node->last_valid = jiffies;
  120. spin_lock_bh(&neigh_node->tq_lock);
  121. ring_buffer_set(neigh_node->tq_recv,
  122. &neigh_node->tq_index,
  123. batman_ogm_packet->tq);
  124. neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
  125. spin_unlock_bh(&neigh_node->tq_lock);
  126. if (!is_duplicate) {
  127. orig_node->last_ttl = batman_ogm_packet->ttl;
  128. neigh_node->last_ttl = batman_ogm_packet->ttl;
  129. }
  130. bonding_candidate_add(orig_node, neigh_node);
  131. /* if this neighbor already is our next hop there is nothing
  132. * to change */
  133. router = orig_node_get_router(orig_node);
  134. if (router == neigh_node)
  135. goto update_tt;
  136. /* if this neighbor does not offer a better TQ we won't consider it */
  137. if (router && (router->tq_avg > neigh_node->tq_avg))
  138. goto update_tt;
  139. /* if the TQ is the same and the link not more symmetric we
  140. * won't consider it either */
  141. if (router && (neigh_node->tq_avg == router->tq_avg)) {
  142. orig_node_tmp = router->orig_node;
  143. spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
  144. bcast_own_sum_orig =
  145. orig_node_tmp->bcast_own_sum[if_incoming->if_num];
  146. spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
  147. orig_node_tmp = neigh_node->orig_node;
  148. spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
  149. bcast_own_sum_neigh =
  150. orig_node_tmp->bcast_own_sum[if_incoming->if_num];
  151. spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
  152. if (bcast_own_sum_orig >= bcast_own_sum_neigh)
  153. goto update_tt;
  154. }
  155. update_route(bat_priv, orig_node, neigh_node);
  156. update_tt:
  157. /* I have to check for transtable changes only if the OGM has been
  158. * sent through a primary interface */
  159. if (((batman_ogm_packet->orig != ethhdr->h_source) &&
  160. (batman_ogm_packet->ttl > 2)) ||
  161. (batman_ogm_packet->flags & PRIMARIES_FIRST_HOP))
  162. tt_update_orig(bat_priv, orig_node, tt_buff,
  163. batman_ogm_packet->tt_num_changes,
  164. batman_ogm_packet->ttvn,
  165. batman_ogm_packet->tt_crc);
  166. if (orig_node->gw_flags != batman_ogm_packet->gw_flags)
  167. gw_node_update(bat_priv, orig_node,
  168. batman_ogm_packet->gw_flags);
  169. orig_node->gw_flags = batman_ogm_packet->gw_flags;
  170. /* restart gateway selection if fast or late switching was enabled */
  171. if ((orig_node->gw_flags) &&
  172. (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
  173. (atomic_read(&bat_priv->gw_sel_class) > 2))
  174. gw_check_election(bat_priv, orig_node);
  175. goto out;
  176. unlock:
  177. rcu_read_unlock();
  178. out:
  179. if (neigh_node)
  180. neigh_node_free_ref(neigh_node);
  181. if (router)
  182. neigh_node_free_ref(router);
  183. }
  184. static int bat_ogm_calc_tq(struct orig_node *orig_node,
  185. struct orig_node *orig_neigh_node,
  186. struct batman_ogm_packet *batman_ogm_packet,
  187. struct hard_iface *if_incoming)
  188. {
  189. struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
  190. struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
  191. struct hlist_node *node;
  192. uint8_t total_count;
  193. uint8_t orig_eq_count, neigh_rq_count, tq_own;
  194. int tq_asym_penalty, ret = 0;
  195. /* find corresponding one hop neighbor */
  196. rcu_read_lock();
  197. hlist_for_each_entry_rcu(tmp_neigh_node, node,
  198. &orig_neigh_node->neigh_list, list) {
  199. if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig))
  200. continue;
  201. if (tmp_neigh_node->if_incoming != if_incoming)
  202. continue;
  203. if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
  204. continue;
  205. neigh_node = tmp_neigh_node;
  206. break;
  207. }
  208. rcu_read_unlock();
  209. if (!neigh_node)
  210. neigh_node = create_neighbor(orig_neigh_node,
  211. orig_neigh_node,
  212. orig_neigh_node->orig,
  213. if_incoming);
  214. if (!neigh_node)
  215. goto out;
  216. /* if orig_node is direct neighbor update neigh_node last_valid */
  217. if (orig_node == orig_neigh_node)
  218. neigh_node->last_valid = jiffies;
  219. orig_node->last_valid = jiffies;
  220. /* find packet count of corresponding one hop neighbor */
  221. spin_lock_bh(&orig_node->ogm_cnt_lock);
  222. orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
  223. neigh_rq_count = neigh_node->real_packet_count;
  224. spin_unlock_bh(&orig_node->ogm_cnt_lock);
  225. /* pay attention to not get a value bigger than 100 % */
  226. total_count = (orig_eq_count > neigh_rq_count ?
  227. neigh_rq_count : orig_eq_count);
  228. /* if we have too few packets (too less data) we set tq_own to zero */
  229. /* if we receive too few packets it is not considered bidirectional */
  230. if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
  231. (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
  232. tq_own = 0;
  233. else
  234. /* neigh_node->real_packet_count is never zero as we
  235. * only purge old information when getting new
  236. * information */
  237. tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count;
  238. /*
  239. * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
  240. * affect the nearly-symmetric links only a little, but
  241. * punishes asymmetric links more. This will give a value
  242. * between 0 and TQ_MAX_VALUE
  243. */
  244. tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
  245. (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
  246. (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
  247. (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) /
  248. (TQ_LOCAL_WINDOW_SIZE *
  249. TQ_LOCAL_WINDOW_SIZE *
  250. TQ_LOCAL_WINDOW_SIZE);
  251. batman_ogm_packet->tq = ((batman_ogm_packet->tq * tq_own
  252. * tq_asym_penalty) /
  253. (TQ_MAX_VALUE * TQ_MAX_VALUE));
  254. bat_dbg(DBG_BATMAN, bat_priv,
  255. "bidirectional: "
  256. "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
  257. "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
  258. "total tq: %3i\n",
  259. orig_node->orig, orig_neigh_node->orig, total_count,
  260. neigh_rq_count, tq_own, tq_asym_penalty, batman_ogm_packet->tq);
  261. /* if link has the minimum required transmission quality
  262. * consider it bidirectional */
  263. if (batman_ogm_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
  264. ret = 1;
  265. out:
  266. if (neigh_node)
  267. neigh_node_free_ref(neigh_node);
  268. return ret;
  269. }
  270. /* processes a batman packet for all interfaces, adjusts the sequence number and
  271. * finds out whether it is a duplicate.
  272. * returns:
  273. * 1 the packet is a duplicate
  274. * 0 the packet has not yet been received
  275. * -1 the packet is old and has been received while the seqno window
  276. * was protected. Caller should drop it.
  277. */
  278. static int bat_ogm_update_seqnos(const struct ethhdr *ethhdr,
  279. const struct batman_ogm_packet
  280. *batman_ogm_packet,
  281. const struct hard_iface *if_incoming)
  282. {
  283. struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
  284. struct orig_node *orig_node;
  285. struct neigh_node *tmp_neigh_node;
  286. struct hlist_node *node;
  287. int is_duplicate = 0;
  288. int32_t seq_diff;
  289. int need_update = 0;
  290. int set_mark, ret = -1;
  291. orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig);
  292. if (!orig_node)
  293. return 0;
  294. spin_lock_bh(&orig_node->ogm_cnt_lock);
  295. seq_diff = batman_ogm_packet->seqno - orig_node->last_real_seqno;
  296. /* signalize caller that the packet is to be dropped. */
  297. if (window_protected(bat_priv, seq_diff,
  298. &orig_node->batman_seqno_reset))
  299. goto out;
  300. rcu_read_lock();
  301. hlist_for_each_entry_rcu(tmp_neigh_node, node,
  302. &orig_node->neigh_list, list) {
  303. is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
  304. orig_node->last_real_seqno,
  305. batman_ogm_packet->seqno);
  306. if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
  307. (tmp_neigh_node->if_incoming == if_incoming))
  308. set_mark = 1;
  309. else
  310. set_mark = 0;
  311. /* if the window moved, set the update flag. */
  312. need_update |= bit_get_packet(bat_priv,
  313. tmp_neigh_node->real_bits,
  314. seq_diff, set_mark);
  315. tmp_neigh_node->real_packet_count =
  316. bit_packet_count(tmp_neigh_node->real_bits);
  317. }
  318. rcu_read_unlock();
  319. if (need_update) {
  320. bat_dbg(DBG_BATMAN, bat_priv,
  321. "updating last_seqno: old %d, new %d\n",
  322. orig_node->last_real_seqno, batman_ogm_packet->seqno);
  323. orig_node->last_real_seqno = batman_ogm_packet->seqno;
  324. }
  325. ret = is_duplicate;
  326. out:
  327. spin_unlock_bh(&orig_node->ogm_cnt_lock);
  328. orig_node_free_ref(orig_node);
  329. return ret;
  330. }
  331. static void bat_ogm_process(const struct ethhdr *ethhdr,
  332. struct batman_ogm_packet *batman_ogm_packet,
  333. const unsigned char *tt_buff,
  334. struct hard_iface *if_incoming)
  335. {
  336. struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
  337. struct hard_iface *hard_iface;
  338. struct orig_node *orig_neigh_node, *orig_node;
  339. struct neigh_node *router = NULL, *router_router = NULL;
  340. struct neigh_node *orig_neigh_router = NULL;
  341. int has_directlink_flag;
  342. int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
  343. int is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
  344. int is_duplicate;
  345. uint32_t if_incoming_seqno;
  346. /* Silently drop when the batman packet is actually not a
  347. * correct packet.
  348. *
  349. * This might happen if a packet is padded (e.g. Ethernet has a
  350. * minimum frame length of 64 byte) and the aggregation interprets
  351. * it as an additional length.
  352. *
  353. * TODO: A more sane solution would be to have a bit in the
  354. * batman_ogm_packet to detect whether the packet is the last
  355. * packet in an aggregation. Here we expect that the padding
  356. * is always zero (or not 0x01)
  357. */
  358. if (batman_ogm_packet->packet_type != BAT_OGM)
  359. return;
  360. /* could be changed by schedule_own_packet() */
  361. if_incoming_seqno = atomic_read(&if_incoming->seqno);
  362. has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
  363. is_single_hop_neigh = (compare_eth(ethhdr->h_source,
  364. batman_ogm_packet->orig) ? 1 : 0);
  365. bat_dbg(DBG_BATMAN, bat_priv,
  366. "Received BATMAN packet via NB: %pM, IF: %s [%pM] "
  367. "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, "
  368. "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
  369. ethhdr->h_source, if_incoming->net_dev->name,
  370. if_incoming->net_dev->dev_addr, batman_ogm_packet->orig,
  371. batman_ogm_packet->prev_sender, batman_ogm_packet->seqno,
  372. batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc,
  373. batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq,
  374. batman_ogm_packet->ttl, batman_ogm_packet->version,
  375. has_directlink_flag);
  376. rcu_read_lock();
  377. list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
  378. if (hard_iface->if_status != IF_ACTIVE)
  379. continue;
  380. if (hard_iface->soft_iface != if_incoming->soft_iface)
  381. continue;
  382. if (compare_eth(ethhdr->h_source,
  383. hard_iface->net_dev->dev_addr))
  384. is_my_addr = 1;
  385. if (compare_eth(batman_ogm_packet->orig,
  386. hard_iface->net_dev->dev_addr))
  387. is_my_orig = 1;
  388. if (compare_eth(batman_ogm_packet->prev_sender,
  389. hard_iface->net_dev->dev_addr))
  390. is_my_oldorig = 1;
  391. if (is_broadcast_ether_addr(ethhdr->h_source))
  392. is_broadcast = 1;
  393. }
  394. rcu_read_unlock();
  395. if (batman_ogm_packet->version != COMPAT_VERSION) {
  396. bat_dbg(DBG_BATMAN, bat_priv,
  397. "Drop packet: incompatible batman version (%i)\n",
  398. batman_ogm_packet->version);
  399. return;
  400. }
  401. if (is_my_addr) {
  402. bat_dbg(DBG_BATMAN, bat_priv,
  403. "Drop packet: received my own broadcast (sender: %pM"
  404. ")\n",
  405. ethhdr->h_source);
  406. return;
  407. }
  408. if (is_broadcast) {
  409. bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
  410. "ignoring all packets with broadcast source addr (sender: %pM"
  411. ")\n", ethhdr->h_source);
  412. return;
  413. }
  414. if (is_my_orig) {
  415. unsigned long *word;
  416. int offset;
  417. orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
  418. if (!orig_neigh_node)
  419. return;
  420. /* neighbor has to indicate direct link and it has to
  421. * come via the corresponding interface */
  422. /* save packet seqno for bidirectional check */
  423. if (has_directlink_flag &&
  424. compare_eth(if_incoming->net_dev->dev_addr,
  425. batman_ogm_packet->orig)) {
  426. offset = if_incoming->if_num * NUM_WORDS;
  427. spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
  428. word = &(orig_neigh_node->bcast_own[offset]);
  429. bit_mark(word,
  430. if_incoming_seqno -
  431. batman_ogm_packet->seqno - 2);
  432. orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
  433. bit_packet_count(word);
  434. spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
  435. }
  436. bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
  437. "originator packet from myself (via neighbor)\n");
  438. orig_node_free_ref(orig_neigh_node);
  439. return;
  440. }
  441. if (is_my_oldorig) {
  442. bat_dbg(DBG_BATMAN, bat_priv,
  443. "Drop packet: ignoring all rebroadcast echos (sender: "
  444. "%pM)\n", ethhdr->h_source);
  445. return;
  446. }
  447. orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig);
  448. if (!orig_node)
  449. return;
  450. is_duplicate = bat_ogm_update_seqnos(ethhdr, batman_ogm_packet,
  451. if_incoming);
  452. if (is_duplicate == -1) {
  453. bat_dbg(DBG_BATMAN, bat_priv,
  454. "Drop packet: packet within seqno protection time "
  455. "(sender: %pM)\n", ethhdr->h_source);
  456. goto out;
  457. }
  458. if (batman_ogm_packet->tq == 0) {
  459. bat_dbg(DBG_BATMAN, bat_priv,
  460. "Drop packet: originator packet with tq equal 0\n");
  461. goto out;
  462. }
  463. router = orig_node_get_router(orig_node);
  464. if (router)
  465. router_router = orig_node_get_router(router->orig_node);
  466. /* avoid temporary routing loops */
  467. if (router && router_router &&
  468. (compare_eth(router->addr, batman_ogm_packet->prev_sender)) &&
  469. !(compare_eth(batman_ogm_packet->orig,
  470. batman_ogm_packet->prev_sender)) &&
  471. (compare_eth(router->addr, router_router->addr))) {
  472. bat_dbg(DBG_BATMAN, bat_priv,
  473. "Drop packet: ignoring all rebroadcast packets that "
  474. "may make me loop (sender: %pM)\n", ethhdr->h_source);
  475. goto out;
  476. }
  477. /* if sender is a direct neighbor the sender mac equals
  478. * originator mac */
  479. orig_neigh_node = (is_single_hop_neigh ?
  480. orig_node :
  481. get_orig_node(bat_priv, ethhdr->h_source));
  482. if (!orig_neigh_node)
  483. goto out;
  484. orig_neigh_router = orig_node_get_router(orig_neigh_node);
  485. /* drop packet if sender is not a direct neighbor and if we
  486. * don't route towards it */
  487. if (!is_single_hop_neigh && (!orig_neigh_router)) {
  488. bat_dbg(DBG_BATMAN, bat_priv,
  489. "Drop packet: OGM via unknown neighbor!\n");
  490. goto out_neigh;
  491. }
  492. is_bidirectional = bat_ogm_calc_tq(orig_node, orig_neigh_node,
  493. batman_ogm_packet, if_incoming);
  494. bonding_save_primary(orig_node, orig_neigh_node, batman_ogm_packet);
  495. /* update ranking if it is not a duplicate or has the same
  496. * seqno and similar ttl as the non-duplicate */
  497. if (is_bidirectional &&
  498. (!is_duplicate ||
  499. ((orig_node->last_real_seqno == batman_ogm_packet->seqno) &&
  500. (orig_node->last_ttl - 3 <= batman_ogm_packet->ttl))))
  501. bat_ogm_orig_update(bat_priv, orig_node, ethhdr,
  502. batman_ogm_packet, if_incoming,
  503. tt_buff, is_duplicate);
  504. /* is single hop (direct) neighbor */
  505. if (is_single_hop_neigh) {
  506. /* mark direct link on incoming interface */
  507. schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet,
  508. 1, if_incoming);
  509. bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
  510. "rebroadcast neighbor packet with direct link flag\n");
  511. goto out_neigh;
  512. }
  513. /* multihop originator */
  514. if (!is_bidirectional) {
  515. bat_dbg(DBG_BATMAN, bat_priv,
  516. "Drop packet: not received via bidirectional link\n");
  517. goto out_neigh;
  518. }
  519. if (is_duplicate) {
  520. bat_dbg(DBG_BATMAN, bat_priv,
  521. "Drop packet: duplicate packet received\n");
  522. goto out_neigh;
  523. }
  524. bat_dbg(DBG_BATMAN, bat_priv,
  525. "Forwarding packet: rebroadcast originator packet\n");
  526. schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet,
  527. 0, if_incoming);
  528. out_neigh:
  529. if ((orig_neigh_node) && (!is_single_hop_neigh))
  530. orig_node_free_ref(orig_neigh_node);
  531. out:
  532. if (router)
  533. neigh_node_free_ref(router);
  534. if (router_router)
  535. neigh_node_free_ref(router_router);
  536. if (orig_neigh_router)
  537. neigh_node_free_ref(orig_neigh_router);
  538. orig_node_free_ref(orig_node);
  539. }
  540. void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff,
  541. int packet_len, struct hard_iface *if_incoming)
  542. {
  543. struct batman_ogm_packet *batman_ogm_packet;
  544. int buff_pos = 0;
  545. unsigned char *tt_buff;
  546. batman_ogm_packet = (struct batman_ogm_packet *)packet_buff;
  547. /* unpack the aggregated packets and process them one by one */
  548. do {
  549. /* network to host order for our 32bit seqno and the
  550. orig_interval */
  551. batman_ogm_packet->seqno = ntohl(batman_ogm_packet->seqno);
  552. batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc);
  553. tt_buff = packet_buff + buff_pos + BATMAN_OGM_LEN;
  554. bat_ogm_process(ethhdr, batman_ogm_packet,
  555. tt_buff, if_incoming);
  556. buff_pos += BATMAN_OGM_LEN +
  557. tt_len(batman_ogm_packet->tt_num_changes);
  558. batman_ogm_packet = (struct batman_ogm_packet *)
  559. (packet_buff + buff_pos);
  560. } while (bat_ogm_aggr_packet(buff_pos, packet_len,
  561. batman_ogm_packet->tt_num_changes));
  562. }