multicast.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. /* Copyright (C) 2014 B.A.T.M.A.N. contributors:
  2. *
  3. * Linus Lüssing
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of version 2 of the GNU General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "main.h"
  18. #include "multicast.h"
  19. #include "originator.h"
  20. #include "hard-interface.h"
  21. #include "translation-table.h"
  22. /**
  23. * batadv_mcast_mla_softif_get - get softif multicast listeners
  24. * @dev: the device to collect multicast addresses from
  25. * @mcast_list: a list to put found addresses into
  26. *
  27. * Collect multicast addresses of the local multicast listeners
  28. * on the given soft interface, dev, in the given mcast_list.
  29. *
  30. * Returns -ENOMEM on memory allocation error or the number of
  31. * items added to the mcast_list otherwise.
  32. */
  33. static int batadv_mcast_mla_softif_get(struct net_device *dev,
  34. struct hlist_head *mcast_list)
  35. {
  36. struct netdev_hw_addr *mc_list_entry;
  37. struct batadv_hw_addr *new;
  38. int ret = 0;
  39. netif_addr_lock_bh(dev);
  40. netdev_for_each_mc_addr(mc_list_entry, dev) {
  41. new = kmalloc(sizeof(*new), GFP_ATOMIC);
  42. if (!new) {
  43. ret = -ENOMEM;
  44. break;
  45. }
  46. ether_addr_copy(new->addr, mc_list_entry->addr);
  47. hlist_add_head(&new->list, mcast_list);
  48. ret++;
  49. }
  50. netif_addr_unlock_bh(dev);
  51. return ret;
  52. }
  53. /**
  54. * batadv_mcast_mla_is_duplicate - check whether an address is in a list
  55. * @mcast_addr: the multicast address to check
  56. * @mcast_list: the list with multicast addresses to search in
  57. *
  58. * Returns true if the given address is already in the given list.
  59. * Otherwise returns false.
  60. */
  61. static bool batadv_mcast_mla_is_duplicate(uint8_t *mcast_addr,
  62. struct hlist_head *mcast_list)
  63. {
  64. struct batadv_hw_addr *mcast_entry;
  65. hlist_for_each_entry(mcast_entry, mcast_list, list)
  66. if (batadv_compare_eth(mcast_entry->addr, mcast_addr))
  67. return true;
  68. return false;
  69. }
  70. /**
  71. * batadv_mcast_mla_list_free - free a list of multicast addresses
  72. * @mcast_list: the list to free
  73. *
  74. * Removes and frees all items in the given mcast_list.
  75. */
  76. static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
  77. {
  78. struct batadv_hw_addr *mcast_entry;
  79. struct hlist_node *tmp;
  80. hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
  81. hlist_del(&mcast_entry->list);
  82. kfree(mcast_entry);
  83. }
  84. }
  85. /**
  86. * batadv_mcast_mla_tt_retract - clean up multicast listener announcements
  87. * @bat_priv: the bat priv with all the soft interface information
  88. * @mcast_list: a list of addresses which should _not_ be removed
  89. *
  90. * Retracts the announcement of any multicast listener from the
  91. * translation table except the ones listed in the given mcast_list.
  92. *
  93. * If mcast_list is NULL then all are retracted.
  94. */
  95. static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
  96. struct hlist_head *mcast_list)
  97. {
  98. struct batadv_hw_addr *mcast_entry;
  99. struct hlist_node *tmp;
  100. hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
  101. list) {
  102. if (mcast_list &&
  103. batadv_mcast_mla_is_duplicate(mcast_entry->addr,
  104. mcast_list))
  105. continue;
  106. batadv_tt_local_remove(bat_priv, mcast_entry->addr,
  107. BATADV_NO_FLAGS,
  108. "mcast TT outdated", false);
  109. hlist_del(&mcast_entry->list);
  110. kfree(mcast_entry);
  111. }
  112. }
  113. /**
  114. * batadv_mcast_mla_tt_add - add multicast listener announcements
  115. * @bat_priv: the bat priv with all the soft interface information
  116. * @mcast_list: a list of addresses which are going to get added
  117. *
  118. * Adds multicast listener announcements from the given mcast_list to the
  119. * translation table if they have not been added yet.
  120. */
  121. static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
  122. struct hlist_head *mcast_list)
  123. {
  124. struct batadv_hw_addr *mcast_entry;
  125. struct hlist_node *tmp;
  126. if (!mcast_list)
  127. return;
  128. hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) {
  129. if (batadv_mcast_mla_is_duplicate(mcast_entry->addr,
  130. &bat_priv->mcast.mla_list))
  131. continue;
  132. if (!batadv_tt_local_add(bat_priv->soft_iface,
  133. mcast_entry->addr, BATADV_NO_FLAGS,
  134. BATADV_NULL_IFINDEX, BATADV_NO_MARK))
  135. continue;
  136. hlist_del(&mcast_entry->list);
  137. hlist_add_head(&mcast_entry->list, &bat_priv->mcast.mla_list);
  138. }
  139. }
  140. /**
  141. * batadv_mcast_has_bridge - check whether the soft-iface is bridged
  142. * @bat_priv: the bat priv with all the soft interface information
  143. *
  144. * Checks whether there is a bridge on top of our soft interface. Returns
  145. * true if so, false otherwise.
  146. */
  147. static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv)
  148. {
  149. struct net_device *upper = bat_priv->soft_iface;
  150. rcu_read_lock();
  151. do {
  152. upper = netdev_master_upper_dev_get_rcu(upper);
  153. } while (upper && !(upper->priv_flags & IFF_EBRIDGE));
  154. rcu_read_unlock();
  155. return upper;
  156. }
  157. /**
  158. * batadv_mcast_mla_tvlv_update - update multicast tvlv
  159. * @bat_priv: the bat priv with all the soft interface information
  160. *
  161. * Updates the own multicast tvlv with our current multicast related settings,
  162. * capabilities and inabilities.
  163. *
  164. * Returns true if the tvlv container is registered afterwards. Otherwise
  165. * returns false.
  166. */
  167. static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv)
  168. {
  169. struct batadv_tvlv_mcast_data mcast_data;
  170. mcast_data.flags = BATADV_NO_FLAGS;
  171. memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved));
  172. /* Avoid attaching MLAs, if there is a bridge on top of our soft
  173. * interface, we don't support that yet (TODO)
  174. */
  175. if (batadv_mcast_has_bridge(bat_priv)) {
  176. if (bat_priv->mcast.enabled) {
  177. batadv_tvlv_container_unregister(bat_priv,
  178. BATADV_TVLV_MCAST, 1);
  179. bat_priv->mcast.enabled = false;
  180. }
  181. return false;
  182. }
  183. if (!bat_priv->mcast.enabled ||
  184. mcast_data.flags != bat_priv->mcast.flags) {
  185. batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1,
  186. &mcast_data, sizeof(mcast_data));
  187. bat_priv->mcast.flags = mcast_data.flags;
  188. bat_priv->mcast.enabled = true;
  189. }
  190. return true;
  191. }
  192. /**
  193. * batadv_mcast_mla_update - update the own MLAs
  194. * @bat_priv: the bat priv with all the soft interface information
  195. *
  196. * Updates the own multicast listener announcements in the translation
  197. * table as well as the own, announced multicast tvlv container.
  198. */
  199. void batadv_mcast_mla_update(struct batadv_priv *bat_priv)
  200. {
  201. struct net_device *soft_iface = bat_priv->soft_iface;
  202. struct hlist_head mcast_list = HLIST_HEAD_INIT;
  203. int ret;
  204. if (!batadv_mcast_mla_tvlv_update(bat_priv))
  205. goto update;
  206. ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list);
  207. if (ret < 0)
  208. goto out;
  209. update:
  210. batadv_mcast_mla_tt_retract(bat_priv, &mcast_list);
  211. batadv_mcast_mla_tt_add(bat_priv, &mcast_list);
  212. out:
  213. batadv_mcast_mla_list_free(&mcast_list);
  214. }
  215. /**
  216. * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential
  217. * @bat_priv: the bat priv with all the soft interface information
  218. * @skb: the IPv4 packet to check
  219. * @is_unsnoopable: stores whether the destination is snoopable
  220. *
  221. * Checks whether the given IPv4 packet has the potential to be forwarded with a
  222. * mode more optimal than classic flooding.
  223. *
  224. * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM in case of
  225. * memory allocation failure.
  226. */
  227. static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv,
  228. struct sk_buff *skb,
  229. bool *is_unsnoopable)
  230. {
  231. struct iphdr *iphdr;
  232. /* We might fail due to out-of-memory -> drop it */
  233. if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr)))
  234. return -ENOMEM;
  235. iphdr = ip_hdr(skb);
  236. /* TODO: Implement Multicast Router Discovery (RFC4286),
  237. * then allow scope > link local, too
  238. */
  239. if (!ipv4_is_local_multicast(iphdr->daddr))
  240. return -EINVAL;
  241. /* link-local multicast listeners behind a bridge are
  242. * not snoopable (see RFC4541, section 2.1.2.2)
  243. */
  244. *is_unsnoopable = true;
  245. return 0;
  246. }
  247. /**
  248. * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential
  249. * @bat_priv: the bat priv with all the soft interface information
  250. * @skb: the IPv6 packet to check
  251. * @is_unsnoopable: stores whether the destination is snoopable
  252. *
  253. * Checks whether the given IPv6 packet has the potential to be forwarded with a
  254. * mode more optimal than classic flooding.
  255. *
  256. * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
  257. * of memory.
  258. */
  259. static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv,
  260. struct sk_buff *skb,
  261. bool *is_unsnoopable)
  262. {
  263. struct ipv6hdr *ip6hdr;
  264. /* We might fail due to out-of-memory -> drop it */
  265. if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr)))
  266. return -ENOMEM;
  267. ip6hdr = ipv6_hdr(skb);
  268. /* TODO: Implement Multicast Router Discovery (RFC4286),
  269. * then allow scope > link local, too
  270. */
  271. if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL)
  272. return -EINVAL;
  273. /* link-local-all-nodes multicast listeners behind a bridge are
  274. * not snoopable (see RFC4541, section 3, paragraph 3)
  275. */
  276. if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr))
  277. *is_unsnoopable = true;
  278. return 0;
  279. }
  280. /**
  281. * batadv_mcast_forw_mode_check - check for optimized forwarding potential
  282. * @bat_priv: the bat priv with all the soft interface information
  283. * @skb: the multicast frame to check
  284. * @is_unsnoopable: stores whether the destination is snoopable
  285. *
  286. * Checks whether the given multicast ethernet frame has the potential to be
  287. * forwarded with a mode more optimal than classic flooding.
  288. *
  289. * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out
  290. * of memory.
  291. */
  292. static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
  293. struct sk_buff *skb,
  294. bool *is_unsnoopable)
  295. {
  296. struct ethhdr *ethhdr = eth_hdr(skb);
  297. if (!atomic_read(&bat_priv->multicast_mode))
  298. return -EINVAL;
  299. if (atomic_read(&bat_priv->mcast.num_disabled))
  300. return -EINVAL;
  301. switch (ntohs(ethhdr->h_proto)) {
  302. case ETH_P_IP:
  303. return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb,
  304. is_unsnoopable);
  305. case ETH_P_IPV6:
  306. return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb,
  307. is_unsnoopable);
  308. default:
  309. return -EINVAL;
  310. }
  311. }
  312. /**
  313. * batadv_mcast_want_all_ip_count - count nodes with unspecific mcast interest
  314. * @bat_priv: the bat priv with all the soft interface information
  315. * @ethhdr: ethernet header of a packet
  316. *
  317. * Returns the number of nodes which want all IPv4 multicast traffic if the
  318. * given ethhdr is from an IPv4 packet or the number of nodes which want all
  319. * IPv6 traffic if it matches an IPv6 packet.
  320. */
  321. static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv,
  322. struct ethhdr *ethhdr)
  323. {
  324. switch (ntohs(ethhdr->h_proto)) {
  325. case ETH_P_IP:
  326. return atomic_read(&bat_priv->mcast.num_want_all_ipv4);
  327. case ETH_P_IPV6:
  328. return atomic_read(&bat_priv->mcast.num_want_all_ipv6);
  329. default:
  330. /* we shouldn't be here... */
  331. return 0;
  332. }
  333. }
  334. /**
  335. * batadv_mcast_forw_tt_node_get - get a multicast tt node
  336. * @bat_priv: the bat priv with all the soft interface information
  337. * @ethhdr: the ether header containing the multicast destination
  338. *
  339. * Returns an orig_node matching the multicast address provided by ethhdr
  340. * via a translation table lookup. This increases the returned nodes refcount.
  341. */
  342. static struct batadv_orig_node *
  343. batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv,
  344. struct ethhdr *ethhdr)
  345. {
  346. return batadv_transtable_search(bat_priv, ethhdr->h_source,
  347. ethhdr->h_dest, BATADV_NO_FLAGS);
  348. }
  349. /**
  350. * batadv_mcast_want_forw_ipv4_node_get - get a node with an ipv4 flag
  351. * @bat_priv: the bat priv with all the soft interface information
  352. *
  353. * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and
  354. * increases its refcount.
  355. */
  356. static struct batadv_orig_node *
  357. batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
  358. {
  359. struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
  360. rcu_read_lock();
  361. hlist_for_each_entry_rcu(tmp_orig_node,
  362. &bat_priv->mcast.want_all_ipv4_list,
  363. mcast_want_all_ipv4_node) {
  364. if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
  365. continue;
  366. orig_node = tmp_orig_node;
  367. break;
  368. }
  369. rcu_read_unlock();
  370. return orig_node;
  371. }
  372. /**
  373. * batadv_mcast_want_forw_ipv6_node_get - get a node with an ipv6 flag
  374. * @bat_priv: the bat priv with all the soft interface information
  375. *
  376. * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set
  377. * and increases its refcount.
  378. */
  379. static struct batadv_orig_node *
  380. batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
  381. {
  382. struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
  383. rcu_read_lock();
  384. hlist_for_each_entry_rcu(tmp_orig_node,
  385. &bat_priv->mcast.want_all_ipv6_list,
  386. mcast_want_all_ipv6_node) {
  387. if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
  388. continue;
  389. orig_node = tmp_orig_node;
  390. break;
  391. }
  392. rcu_read_unlock();
  393. return orig_node;
  394. }
  395. /**
  396. * batadv_mcast_want_forw_ip_node_get - get a node with an ipv4/ipv6 flag
  397. * @bat_priv: the bat priv with all the soft interface information
  398. * @ethhdr: an ethernet header to determine the protocol family from
  399. *
  400. * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or
  401. * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and
  402. * increases its refcount.
  403. */
  404. static struct batadv_orig_node *
  405. batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv,
  406. struct ethhdr *ethhdr)
  407. {
  408. switch (ntohs(ethhdr->h_proto)) {
  409. case ETH_P_IP:
  410. return batadv_mcast_forw_ipv4_node_get(bat_priv);
  411. case ETH_P_IPV6:
  412. return batadv_mcast_forw_ipv6_node_get(bat_priv);
  413. default:
  414. /* we shouldn't be here... */
  415. return NULL;
  416. }
  417. }
  418. /**
  419. * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag
  420. * @bat_priv: the bat priv with all the soft interface information
  421. *
  422. * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag
  423. * set and increases its refcount.
  424. */
  425. static struct batadv_orig_node *
  426. batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv)
  427. {
  428. struct batadv_orig_node *tmp_orig_node, *orig_node = NULL;
  429. rcu_read_lock();
  430. hlist_for_each_entry_rcu(tmp_orig_node,
  431. &bat_priv->mcast.want_all_unsnoopables_list,
  432. mcast_want_all_unsnoopables_node) {
  433. if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
  434. continue;
  435. orig_node = tmp_orig_node;
  436. break;
  437. }
  438. rcu_read_unlock();
  439. return orig_node;
  440. }
  441. /**
  442. * batadv_mcast_forw_mode - check on how to forward a multicast packet
  443. * @bat_priv: the bat priv with all the soft interface information
  444. * @skb: The multicast packet to check
  445. * @orig: an originator to be set to forward the skb to
  446. *
  447. * Returns the forwarding mode as enum batadv_forw_mode and in case of
  448. * BATADV_FORW_SINGLE set the orig to the single originator the skb
  449. * should be forwarded to.
  450. */
  451. enum batadv_forw_mode
  452. batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
  453. struct batadv_orig_node **orig)
  454. {
  455. int ret, tt_count, ip_count, unsnoop_count, total_count;
  456. bool is_unsnoopable = false;
  457. struct ethhdr *ethhdr;
  458. ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable);
  459. if (ret == -ENOMEM)
  460. return BATADV_FORW_NONE;
  461. else if (ret < 0)
  462. return BATADV_FORW_ALL;
  463. ethhdr = eth_hdr(skb);
  464. tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest,
  465. BATADV_NO_FLAGS);
  466. ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr);
  467. unsnoop_count = !is_unsnoopable ? 0 :
  468. atomic_read(&bat_priv->mcast.num_want_all_unsnoopables);
  469. total_count = tt_count + ip_count + unsnoop_count;
  470. switch (total_count) {
  471. case 1:
  472. if (tt_count)
  473. *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr);
  474. else if (ip_count)
  475. *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr);
  476. else if (unsnoop_count)
  477. *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv);
  478. if (*orig)
  479. return BATADV_FORW_SINGLE;
  480. /* fall through */
  481. case 0:
  482. return BATADV_FORW_NONE;
  483. default:
  484. return BATADV_FORW_ALL;
  485. }
  486. }
  487. /**
  488. * batadv_mcast_want_unsnoop_update - update unsnoop counter and list
  489. * @bat_priv: the bat priv with all the soft interface information
  490. * @orig: the orig_node which multicast state might have changed of
  491. * @mcast_flags: flags indicating the new multicast state
  492. *
  493. * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator,
  494. * orig, has toggled then this method updates counter and list accordingly.
  495. */
  496. static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
  497. struct batadv_orig_node *orig,
  498. uint8_t mcast_flags)
  499. {
  500. /* switched from flag unset to set */
  501. if (mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
  502. !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)) {
  503. atomic_inc(&bat_priv->mcast.num_want_all_unsnoopables);
  504. spin_lock_bh(&bat_priv->mcast.want_lists_lock);
  505. hlist_add_head_rcu(&orig->mcast_want_all_unsnoopables_node,
  506. &bat_priv->mcast.want_all_unsnoopables_list);
  507. spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
  508. /* switched from flag set to unset */
  509. } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) &&
  510. orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) {
  511. atomic_dec(&bat_priv->mcast.num_want_all_unsnoopables);
  512. spin_lock_bh(&bat_priv->mcast.want_lists_lock);
  513. hlist_del_rcu(&orig->mcast_want_all_unsnoopables_node);
  514. spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
  515. }
  516. }
  517. /**
  518. * batadv_mcast_want_ipv4_update - update want-all-ipv4 counter and list
  519. * @bat_priv: the bat priv with all the soft interface information
  520. * @orig: the orig_node which multicast state might have changed of
  521. * @mcast_flags: flags indicating the new multicast state
  522. *
  523. * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has
  524. * toggled then this method updates counter and list accordingly.
  525. */
  526. static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
  527. struct batadv_orig_node *orig,
  528. uint8_t mcast_flags)
  529. {
  530. /* switched from flag unset to set */
  531. if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4 &&
  532. !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)) {
  533. atomic_inc(&bat_priv->mcast.num_want_all_ipv4);
  534. spin_lock_bh(&bat_priv->mcast.want_lists_lock);
  535. hlist_add_head_rcu(&orig->mcast_want_all_ipv4_node,
  536. &bat_priv->mcast.want_all_ipv4_list);
  537. spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
  538. /* switched from flag set to unset */
  539. } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) &&
  540. orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) {
  541. atomic_dec(&bat_priv->mcast.num_want_all_ipv4);
  542. spin_lock_bh(&bat_priv->mcast.want_lists_lock);
  543. hlist_del_rcu(&orig->mcast_want_all_ipv4_node);
  544. spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
  545. }
  546. }
  547. /**
  548. * batadv_mcast_want_ipv6_update - update want-all-ipv6 counter and list
  549. * @bat_priv: the bat priv with all the soft interface information
  550. * @orig: the orig_node which multicast state might have changed of
  551. * @mcast_flags: flags indicating the new multicast state
  552. *
  553. * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has
  554. * toggled then this method updates counter and list accordingly.
  555. */
  556. static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
  557. struct batadv_orig_node *orig,
  558. uint8_t mcast_flags)
  559. {
  560. /* switched from flag unset to set */
  561. if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6 &&
  562. !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)) {
  563. atomic_inc(&bat_priv->mcast.num_want_all_ipv6);
  564. spin_lock_bh(&bat_priv->mcast.want_lists_lock);
  565. hlist_add_head_rcu(&orig->mcast_want_all_ipv6_node,
  566. &bat_priv->mcast.want_all_ipv6_list);
  567. spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
  568. /* switched from flag set to unset */
  569. } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) &&
  570. orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) {
  571. atomic_dec(&bat_priv->mcast.num_want_all_ipv6);
  572. spin_lock_bh(&bat_priv->mcast.want_lists_lock);
  573. hlist_del_rcu(&orig->mcast_want_all_ipv6_node);
  574. spin_unlock_bh(&bat_priv->mcast.want_lists_lock);
  575. }
  576. }
  577. /**
  578. * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container
  579. * @bat_priv: the bat priv with all the soft interface information
  580. * @orig: the orig_node of the ogm
  581. * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
  582. * @tvlv_value: tvlv buffer containing the multicast data
  583. * @tvlv_value_len: tvlv buffer length
  584. */
  585. static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
  586. struct batadv_orig_node *orig,
  587. uint8_t flags,
  588. void *tvlv_value,
  589. uint16_t tvlv_value_len)
  590. {
  591. bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
  592. uint8_t mcast_flags = BATADV_NO_FLAGS;
  593. bool orig_initialized;
  594. orig_initialized = orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST;
  595. /* If mcast support is turned on decrease the disabled mcast node
  596. * counter only if we had increased it for this node before. If this
  597. * is a completely new orig_node no need to decrease the counter.
  598. */
  599. if (orig_mcast_enabled &&
  600. !(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) {
  601. if (orig_initialized)
  602. atomic_dec(&bat_priv->mcast.num_disabled);
  603. orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST;
  604. /* If mcast support is being switched off increase the disabled
  605. * mcast node counter.
  606. */
  607. } else if (!orig_mcast_enabled &&
  608. orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) {
  609. atomic_inc(&bat_priv->mcast.num_disabled);
  610. orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST;
  611. }
  612. orig->capa_initialized |= BATADV_ORIG_CAPA_HAS_MCAST;
  613. if (orig_mcast_enabled && tvlv_value &&
  614. (tvlv_value_len >= sizeof(mcast_flags)))
  615. mcast_flags = *(uint8_t *)tvlv_value;
  616. batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags);
  617. batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags);
  618. batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags);
  619. orig->mcast_flags = mcast_flags;
  620. }
  621. /**
  622. * batadv_mcast_init - initialize the multicast optimizations structures
  623. * @bat_priv: the bat priv with all the soft interface information
  624. */
  625. void batadv_mcast_init(struct batadv_priv *bat_priv)
  626. {
  627. batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1,
  628. NULL, BATADV_TVLV_MCAST, 1,
  629. BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
  630. }
  631. /**
  632. * batadv_mcast_free - free the multicast optimizations structures
  633. * @bat_priv: the bat priv with all the soft interface information
  634. */
  635. void batadv_mcast_free(struct batadv_priv *bat_priv)
  636. {
  637. batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
  638. batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1);
  639. batadv_mcast_mla_tt_retract(bat_priv, NULL);
  640. }
  641. /**
  642. * batadv_mcast_purge_orig - reset originator global mcast state modifications
  643. * @orig: the originator which is going to get purged
  644. */
  645. void batadv_mcast_purge_orig(struct batadv_orig_node *orig)
  646. {
  647. struct batadv_priv *bat_priv = orig->bat_priv;
  648. if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST))
  649. atomic_dec(&bat_priv->mcast.num_disabled);
  650. batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS);
  651. batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS);
  652. batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS);
  653. }