vxlan_multicast.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Vxlan multicast group handling
  4. *
  5. */
  6. #include <linux/kernel.h>
  7. #include <net/net_namespace.h>
  8. #include <net/sock.h>
  9. #include <linux/igmp.h>
  10. #include <net/vxlan.h>
  11. #include "vxlan_private.h"
  12. /* Update multicast group membership when first VNI on
  13. * multicast address is brought up
  14. */
  15. int vxlan_igmp_join(struct vxlan_dev *vxlan, union vxlan_addr *rip,
  16. int rifindex)
  17. {
  18. union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip);
  19. int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex);
  20. int ret = -EINVAL;
  21. struct sock *sk;
  22. if (ip->sa.sa_family == AF_INET) {
  23. struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
  24. struct ip_mreqn mreq = {
  25. .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr,
  26. .imr_ifindex = ifindex,
  27. };
  28. sk = sock4->sock->sk;
  29. lock_sock(sk);
  30. ret = ip_mc_join_group(sk, &mreq);
  31. release_sock(sk);
  32. #if IS_ENABLED(CONFIG_IPV6)
  33. } else {
  34. struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
  35. sk = sock6->sock->sk;
  36. lock_sock(sk);
  37. ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
  38. &ip->sin6.sin6_addr);
  39. release_sock(sk);
  40. #endif
  41. }
  42. return ret;
  43. }
  44. int vxlan_igmp_leave(struct vxlan_dev *vxlan, union vxlan_addr *rip,
  45. int rifindex)
  46. {
  47. union vxlan_addr *ip = (rip ? : &vxlan->default_dst.remote_ip);
  48. int ifindex = (rifindex ? : vxlan->default_dst.remote_ifindex);
  49. int ret = -EINVAL;
  50. struct sock *sk;
  51. if (ip->sa.sa_family == AF_INET) {
  52. struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
  53. struct ip_mreqn mreq = {
  54. .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr,
  55. .imr_ifindex = ifindex,
  56. };
  57. sk = sock4->sock->sk;
  58. lock_sock(sk);
  59. ret = ip_mc_leave_group(sk, &mreq);
  60. release_sock(sk);
  61. #if IS_ENABLED(CONFIG_IPV6)
  62. } else {
  63. struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
  64. sk = sock6->sock->sk;
  65. lock_sock(sk);
  66. ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
  67. &ip->sin6.sin6_addr);
  68. release_sock(sk);
  69. #endif
  70. }
  71. return ret;
  72. }
  73. static bool vxlan_group_used_match(union vxlan_addr *ip, int ifindex,
  74. union vxlan_addr *rip, int rifindex)
  75. {
  76. if (!vxlan_addr_multicast(rip))
  77. return false;
  78. if (!vxlan_addr_equal(rip, ip))
  79. return false;
  80. if (rifindex != ifindex)
  81. return false;
  82. return true;
  83. }
  84. static bool vxlan_group_used_by_vnifilter(struct vxlan_dev *vxlan,
  85. union vxlan_addr *ip, int ifindex)
  86. {
  87. struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
  88. struct vxlan_vni_node *v, *tmp;
  89. if (vxlan_group_used_match(ip, ifindex,
  90. &vxlan->default_dst.remote_ip,
  91. vxlan->default_dst.remote_ifindex))
  92. return true;
  93. list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
  94. if (!vxlan_addr_multicast(&v->remote_ip))
  95. continue;
  96. if (vxlan_group_used_match(ip, ifindex,
  97. &v->remote_ip,
  98. vxlan->default_dst.remote_ifindex))
  99. return true;
  100. }
  101. return false;
  102. }
  103. /* See if multicast group is already in use by other ID */
  104. bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev,
  105. __be32 vni, union vxlan_addr *rip, int rifindex)
  106. {
  107. union vxlan_addr *ip = (rip ? : &dev->default_dst.remote_ip);
  108. int ifindex = (rifindex ? : dev->default_dst.remote_ifindex);
  109. struct vxlan_dev *vxlan;
  110. struct vxlan_sock *sock4;
  111. #if IS_ENABLED(CONFIG_IPV6)
  112. struct vxlan_sock *sock6;
  113. #endif
  114. unsigned short family = dev->default_dst.remote_ip.sa.sa_family;
  115. sock4 = rtnl_dereference(dev->vn4_sock);
  116. /* The vxlan_sock is only used by dev, leaving group has
  117. * no effect on other vxlan devices.
  118. */
  119. if (family == AF_INET && sock4 && refcount_read(&sock4->refcnt) == 1)
  120. return false;
  121. #if IS_ENABLED(CONFIG_IPV6)
  122. sock6 = rtnl_dereference(dev->vn6_sock);
  123. if (family == AF_INET6 && sock6 && refcount_read(&sock6->refcnt) == 1)
  124. return false;
  125. #endif
  126. list_for_each_entry(vxlan, &vn->vxlan_list, next) {
  127. if (!netif_running(vxlan->dev) || vxlan == dev)
  128. continue;
  129. if (family == AF_INET &&
  130. rtnl_dereference(vxlan->vn4_sock) != sock4)
  131. continue;
  132. #if IS_ENABLED(CONFIG_IPV6)
  133. if (family == AF_INET6 &&
  134. rtnl_dereference(vxlan->vn6_sock) != sock6)
  135. continue;
  136. #endif
  137. if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
  138. if (!vxlan_group_used_by_vnifilter(vxlan, ip, ifindex))
  139. continue;
  140. } else {
  141. if (!vxlan_group_used_match(ip, ifindex,
  142. &vxlan->default_dst.remote_ip,
  143. vxlan->default_dst.remote_ifindex))
  144. continue;
  145. }
  146. return true;
  147. }
  148. return false;
  149. }
  150. static int vxlan_multicast_join_vnigrp(struct vxlan_dev *vxlan)
  151. {
  152. struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
  153. struct vxlan_vni_node *v, *tmp, *vgood = NULL;
  154. int ret = 0;
  155. list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
  156. if (!vxlan_addr_multicast(&v->remote_ip))
  157. continue;
  158. /* skip if address is same as default address */
  159. if (vxlan_addr_equal(&v->remote_ip,
  160. &vxlan->default_dst.remote_ip))
  161. continue;
  162. ret = vxlan_igmp_join(vxlan, &v->remote_ip, 0);
  163. if (ret == -EADDRINUSE)
  164. ret = 0;
  165. if (ret)
  166. goto out;
  167. vgood = v;
  168. }
  169. out:
  170. if (ret) {
  171. list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
  172. if (!vxlan_addr_multicast(&v->remote_ip))
  173. continue;
  174. if (vxlan_addr_equal(&v->remote_ip,
  175. &vxlan->default_dst.remote_ip))
  176. continue;
  177. vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
  178. if (v == vgood)
  179. break;
  180. }
  181. }
  182. return ret;
  183. }
  184. static int vxlan_multicast_leave_vnigrp(struct vxlan_dev *vxlan)
  185. {
  186. struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
  187. struct vxlan_vni_group *vg = rtnl_dereference(vxlan->vnigrp);
  188. struct vxlan_vni_node *v, *tmp;
  189. int last_err = 0, ret;
  190. list_for_each_entry_safe(v, tmp, &vg->vni_list, vlist) {
  191. if (vxlan_addr_multicast(&v->remote_ip) &&
  192. !vxlan_group_used(vn, vxlan, v->vni, &v->remote_ip,
  193. 0)) {
  194. ret = vxlan_igmp_leave(vxlan, &v->remote_ip, 0);
  195. if (ret)
  196. last_err = ret;
  197. }
  198. }
  199. return last_err;
  200. }
  201. int vxlan_multicast_join(struct vxlan_dev *vxlan)
  202. {
  203. int ret = 0;
  204. if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
  205. ret = vxlan_igmp_join(vxlan, &vxlan->default_dst.remote_ip,
  206. vxlan->default_dst.remote_ifindex);
  207. if (ret == -EADDRINUSE)
  208. ret = 0;
  209. if (ret)
  210. return ret;
  211. }
  212. if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
  213. return vxlan_multicast_join_vnigrp(vxlan);
  214. return 0;
  215. }
  216. int vxlan_multicast_leave(struct vxlan_dev *vxlan)
  217. {
  218. struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
  219. int ret = 0;
  220. if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
  221. !vxlan_group_used(vn, vxlan, 0, NULL, 0)) {
  222. ret = vxlan_igmp_leave(vxlan, &vxlan->default_dst.remote_ip,
  223. vxlan->default_dst.remote_ifindex);
  224. if (ret)
  225. return ret;
  226. }
  227. if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
  228. return vxlan_multicast_leave_vnigrp(vxlan);
  229. return 0;
  230. }