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