aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2015-03-18 13:50:44 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-18 22:05:10 -0400
commit56ef9c909b40483d2c8cb63fcbf83865f162d5ec (patch)
tree71163c8606ff1f64ac22e358c501fbb6667e0ea6 /drivers/net/vxlan.c
parent54ff9ef36bdf84d469a098cbf8e2a103fbc77054 (diff)
vxlan: Move socket initialization to within rtnl scope
Currently, if a multicast join operation fail, the vxlan interface will be UP but not functional, without even a log message informing the user. Now that we can grab socket lock after already having rntl, we don't need to defer socket creation and multicast operations. By not deferring we can do proper error reporting to the user through ip exit code. This patch thus removes all deferred work that vxlan had and put it back inline. Now the socket will only be created, bound and join multicast group when one bring the interface up, and will undo all that as soon as one put the interface down. As vxlan_sock_hold() is not used after this patch, it was removed too. Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c153
1 files changed, 51 insertions, 102 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 8b8ca7492d56..5f749a51f356 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -127,10 +127,6 @@ struct vxlan_dev {
127 __u8 ttl; 127 __u8 ttl;
128 u32 flags; /* VXLAN_F_* in vxlan.h */ 128 u32 flags; /* VXLAN_F_* in vxlan.h */
129 129
130 struct work_struct sock_work;
131 struct work_struct igmp_join;
132 struct work_struct igmp_leave;
133
134 unsigned long age_interval; 130 unsigned long age_interval;
135 struct timer_list age_timer; 131 struct timer_list age_timer;
136 spinlock_t hash_lock; 132 spinlock_t hash_lock;
@@ -144,8 +140,6 @@ struct vxlan_dev {
144static u32 vxlan_salt __read_mostly; 140static u32 vxlan_salt __read_mostly;
145static struct workqueue_struct *vxlan_wq; 141static struct workqueue_struct *vxlan_wq;
146 142
147static void vxlan_sock_work(struct work_struct *work);
148
149#if IS_ENABLED(CONFIG_IPV6) 143#if IS_ENABLED(CONFIG_IPV6)
150static inline 144static inline
151bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) 145bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
@@ -1072,11 +1066,6 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
1072 return false; 1066 return false;
1073} 1067}
1074 1068
1075static void vxlan_sock_hold(struct vxlan_sock *vs)
1076{
1077 atomic_inc(&vs->refcnt);
1078}
1079
1080void vxlan_sock_release(struct vxlan_sock *vs) 1069void vxlan_sock_release(struct vxlan_sock *vs)
1081{ 1070{
1082 struct sock *sk = vs->sock->sk; 1071 struct sock *sk = vs->sock->sk;
@@ -1095,18 +1084,17 @@ void vxlan_sock_release(struct vxlan_sock *vs)
1095} 1084}
1096EXPORT_SYMBOL_GPL(vxlan_sock_release); 1085EXPORT_SYMBOL_GPL(vxlan_sock_release);
1097 1086
1098/* Callback to update multicast group membership when first VNI on 1087/* Update multicast group membership when first VNI on
1099 * multicast asddress is brought up 1088 * multicast asddress is brought up
1100 */ 1089 */
1101static void vxlan_igmp_join(struct work_struct *work) 1090static int vxlan_igmp_join(struct vxlan_dev *vxlan)
1102{ 1091{
1103 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_join);
1104 struct vxlan_sock *vs = vxlan->vn_sock; 1092 struct vxlan_sock *vs = vxlan->vn_sock;
1105 struct sock *sk = vs->sock->sk; 1093 struct sock *sk = vs->sock->sk;
1106 union vxlan_addr *ip = &vxlan->default_dst.remote_ip; 1094 union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
1107 int ifindex = vxlan->default_dst.remote_ifindex; 1095 int ifindex = vxlan->default_dst.remote_ifindex;
1096 int ret;
1108 1097
1109 rtnl_lock();
1110 lock_sock(sk); 1098 lock_sock(sk);
1111 if (ip->sa.sa_family == AF_INET) { 1099 if (ip->sa.sa_family == AF_INET) {
1112 struct ip_mreqn mreq = { 1100 struct ip_mreqn mreq = {
@@ -1114,30 +1102,27 @@ static void vxlan_igmp_join(struct work_struct *work)
1114 .imr_ifindex = ifindex, 1102 .imr_ifindex = ifindex,
1115 }; 1103 };
1116 1104
1117 ip_mc_join_group(sk, &mreq); 1105 ret = ip_mc_join_group(sk, &mreq);
1118#if IS_ENABLED(CONFIG_IPV6) 1106#if IS_ENABLED(CONFIG_IPV6)
1119 } else { 1107 } else {
1120 ipv6_stub->ipv6_sock_mc_join(sk, ifindex, 1108 ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
1121 &ip->sin6.sin6_addr); 1109 &ip->sin6.sin6_addr);
1122#endif 1110#endif
1123 } 1111 }
1124 release_sock(sk); 1112 release_sock(sk);
1125 rtnl_unlock();
1126 1113
1127 vxlan_sock_release(vs); 1114 return ret;
1128 dev_put(vxlan->dev);
1129} 1115}
1130 1116
1131/* Inverse of vxlan_igmp_join when last VNI is brought down */ 1117/* Inverse of vxlan_igmp_join when last VNI is brought down */
1132static void vxlan_igmp_leave(struct work_struct *work) 1118static int vxlan_igmp_leave(struct vxlan_dev *vxlan)
1133{ 1119{
1134 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_leave);
1135 struct vxlan_sock *vs = vxlan->vn_sock; 1120 struct vxlan_sock *vs = vxlan->vn_sock;
1136 struct sock *sk = vs->sock->sk; 1121 struct sock *sk = vs->sock->sk;
1137 union vxlan_addr *ip = &vxlan->default_dst.remote_ip; 1122 union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
1138 int ifindex = vxlan->default_dst.remote_ifindex; 1123 int ifindex = vxlan->default_dst.remote_ifindex;
1124 int ret;
1139 1125
1140 rtnl_lock();
1141 lock_sock(sk); 1126 lock_sock(sk);
1142 if (ip->sa.sa_family == AF_INET) { 1127 if (ip->sa.sa_family == AF_INET) {
1143 struct ip_mreqn mreq = { 1128 struct ip_mreqn mreq = {
@@ -1145,19 +1130,16 @@ static void vxlan_igmp_leave(struct work_struct *work)
1145 .imr_ifindex = ifindex, 1130 .imr_ifindex = ifindex,
1146 }; 1131 };
1147 1132
1148 ip_mc_leave_group(sk, &mreq); 1133 ret = ip_mc_leave_group(sk, &mreq);
1149#if IS_ENABLED(CONFIG_IPV6) 1134#if IS_ENABLED(CONFIG_IPV6)
1150 } else { 1135 } else {
1151 ipv6_stub->ipv6_sock_mc_drop(sk, ifindex, 1136 ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
1152 &ip->sin6.sin6_addr); 1137 &ip->sin6.sin6_addr);
1153#endif 1138#endif
1154 } 1139 }
1155
1156 release_sock(sk); 1140 release_sock(sk);
1157 rtnl_unlock();
1158 1141
1159 vxlan_sock_release(vs); 1142 return ret;
1160 dev_put(vxlan->dev);
1161} 1143}
1162 1144
1163static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh, 1145static struct vxlanhdr *vxlan_remcsum(struct sk_buff *skb, struct vxlanhdr *vh,
@@ -2178,37 +2160,22 @@ static void vxlan_cleanup(unsigned long arg)
2178 2160
2179static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) 2161static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
2180{ 2162{
2163 struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
2181 __u32 vni = vxlan->default_dst.remote_vni; 2164 __u32 vni = vxlan->default_dst.remote_vni;
2182 2165
2183 vxlan->vn_sock = vs; 2166 vxlan->vn_sock = vs;
2167 spin_lock(&vn->sock_lock);
2184 hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni)); 2168 hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
2169 spin_unlock(&vn->sock_lock);
2185} 2170}
2186 2171
2187/* Setup stats when device is created */ 2172/* Setup stats when device is created */
2188static int vxlan_init(struct net_device *dev) 2173static int vxlan_init(struct net_device *dev)
2189{ 2174{
2190 struct vxlan_dev *vxlan = netdev_priv(dev);
2191 struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
2192 struct vxlan_sock *vs;
2193 bool ipv6 = vxlan->flags & VXLAN_F_IPV6;
2194
2195 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 2175 dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
2196 if (!dev->tstats) 2176 if (!dev->tstats)
2197 return -ENOMEM; 2177 return -ENOMEM;
2198 2178
2199 spin_lock(&vn->sock_lock);
2200 vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
2201 vxlan->dst_port, vxlan->flags);
2202 if (vs && atomic_add_unless(&vs->refcnt, 1, 0)) {
2203 /* If we have a socket with same port already, reuse it */
2204 vxlan_vs_add_dev(vs, vxlan);
2205 } else {
2206 /* otherwise make new socket outside of RTNL */
2207 dev_hold(dev);
2208 queue_work(vxlan_wq, &vxlan->sock_work);
2209 }
2210 spin_unlock(&vn->sock_lock);
2211
2212 return 0; 2179 return 0;
2213} 2180}
2214 2181
@@ -2226,12 +2193,9 @@ static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan)
2226static void vxlan_uninit(struct net_device *dev) 2193static void vxlan_uninit(struct net_device *dev)
2227{ 2194{
2228 struct vxlan_dev *vxlan = netdev_priv(dev); 2195 struct vxlan_dev *vxlan = netdev_priv(dev);
2229 struct vxlan_sock *vs = vxlan->vn_sock;
2230 2196
2231 vxlan_fdb_delete_default(vxlan); 2197 vxlan_fdb_delete_default(vxlan);
2232 2198
2233 if (vs)
2234 vxlan_sock_release(vs);
2235 free_percpu(dev->tstats); 2199 free_percpu(dev->tstats);
2236} 2200}
2237 2201
@@ -2239,22 +2203,28 @@ static void vxlan_uninit(struct net_device *dev)
2239static int vxlan_open(struct net_device *dev) 2203static int vxlan_open(struct net_device *dev)
2240{ 2204{
2241 struct vxlan_dev *vxlan = netdev_priv(dev); 2205 struct vxlan_dev *vxlan = netdev_priv(dev);
2242 struct vxlan_sock *vs = vxlan->vn_sock; 2206 struct vxlan_sock *vs;
2207 int ret = 0;
2243 2208
2244 /* socket hasn't been created */ 2209 vs = vxlan_sock_add(vxlan->net, vxlan->dst_port, vxlan_rcv, NULL,
2245 if (!vs) 2210 false, vxlan->flags);
2246 return -ENOTCONN; 2211 if (IS_ERR(vs))
2212 return PTR_ERR(vs);
2213
2214 vxlan_vs_add_dev(vs, vxlan);
2247 2215
2248 if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { 2216 if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
2249 vxlan_sock_hold(vs); 2217 ret = vxlan_igmp_join(vxlan);
2250 dev_hold(dev); 2218 if (ret) {
2251 queue_work(vxlan_wq, &vxlan->igmp_join); 2219 vxlan_sock_release(vs);
2220 return ret;
2221 }
2252 } 2222 }
2253 2223
2254 if (vxlan->age_interval) 2224 if (vxlan->age_interval)
2255 mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL); 2225 mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL);
2256 2226
2257 return 0; 2227 return ret;
2258} 2228}
2259 2229
2260/* Purge the forwarding table */ 2230/* Purge the forwarding table */
@@ -2282,19 +2252,21 @@ static int vxlan_stop(struct net_device *dev)
2282 struct vxlan_dev *vxlan = netdev_priv(dev); 2252 struct vxlan_dev *vxlan = netdev_priv(dev);
2283 struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); 2253 struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
2284 struct vxlan_sock *vs = vxlan->vn_sock; 2254 struct vxlan_sock *vs = vxlan->vn_sock;
2255 int ret = 0;
2285 2256
2286 if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && 2257 if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
2287 !vxlan_group_used(vn, vxlan)) { 2258 !vxlan_group_used(vn, vxlan)) {
2288 vxlan_sock_hold(vs); 2259 ret = vxlan_igmp_leave(vxlan);
2289 dev_hold(dev); 2260 if (ret)
2290 queue_work(vxlan_wq, &vxlan->igmp_leave); 2261 return ret;
2291 } 2262 }
2292 2263
2293 del_timer_sync(&vxlan->age_timer); 2264 del_timer_sync(&vxlan->age_timer);
2294 2265
2295 vxlan_flush(vxlan); 2266 vxlan_flush(vxlan);
2267 vxlan_sock_release(vs);
2296 2268
2297 return 0; 2269 return ret;
2298} 2270}
2299 2271
2300/* Stub, nothing needs to be done. */ 2272/* Stub, nothing needs to be done. */
@@ -2405,9 +2377,6 @@ static void vxlan_setup(struct net_device *dev)
2405 2377
2406 INIT_LIST_HEAD(&vxlan->next); 2378 INIT_LIST_HEAD(&vxlan->next);
2407 spin_lock_init(&vxlan->hash_lock); 2379 spin_lock_init(&vxlan->hash_lock);
2408 INIT_WORK(&vxlan->igmp_join, vxlan_igmp_join);
2409 INIT_WORK(&vxlan->igmp_leave, vxlan_igmp_leave);
2410 INIT_WORK(&vxlan->sock_work, vxlan_sock_work);
2411 2380
2412 init_timer_deferrable(&vxlan->age_timer); 2381 init_timer_deferrable(&vxlan->age_timer);
2413 vxlan->age_timer.function = vxlan_cleanup; 2382 vxlan->age_timer.function = vxlan_cleanup;
@@ -2554,6 +2523,8 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
2554 2523
2555 sock = vxlan_create_sock(net, ipv6, port, flags); 2524 sock = vxlan_create_sock(net, ipv6, port, flags);
2556 if (IS_ERR(sock)) { 2525 if (IS_ERR(sock)) {
2526 pr_info("Cannot bind port %d, err=%ld\n", ntohs(port),
2527 PTR_ERR(sock));
2557 kfree(vs); 2528 kfree(vs);
2558 return ERR_CAST(sock); 2529 return ERR_CAST(sock);
2559 } 2530 }
@@ -2593,45 +2564,23 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
2593 struct vxlan_sock *vs; 2564 struct vxlan_sock *vs;
2594 bool ipv6 = flags & VXLAN_F_IPV6; 2565 bool ipv6 = flags & VXLAN_F_IPV6;
2595 2566
2596 vs = vxlan_socket_create(net, port, rcv, data, flags); 2567 if (!no_share) {
2597 if (!IS_ERR(vs)) 2568 spin_lock(&vn->sock_lock);
2598 return vs; 2569 vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port,
2599 2570 flags);
2600 if (no_share) /* Return error if sharing is not allowed. */ 2571 if (vs && vs->rcv == rcv) {
2601 return vs; 2572 if (!atomic_add_unless(&vs->refcnt, 1, 0))
2602 2573 vs = ERR_PTR(-EBUSY);
2603 spin_lock(&vn->sock_lock); 2574 spin_unlock(&vn->sock_lock);
2604 vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port, flags); 2575 return vs;
2605 if (vs && ((vs->rcv != rcv) || 2576 }
2606 !atomic_add_unless(&vs->refcnt, 1, 0))) 2577 spin_unlock(&vn->sock_lock);
2607 vs = ERR_PTR(-EBUSY); 2578 }
2608 spin_unlock(&vn->sock_lock);
2609
2610 if (!vs)
2611 vs = ERR_PTR(-EINVAL);
2612 2579
2613 return vs; 2580 return vxlan_socket_create(net, port, rcv, data, flags);
2614} 2581}
2615EXPORT_SYMBOL_GPL(vxlan_sock_add); 2582EXPORT_SYMBOL_GPL(vxlan_sock_add);
2616 2583
2617/* Scheduled at device creation to bind to a socket */
2618static void vxlan_sock_work(struct work_struct *work)
2619{
2620 struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, sock_work);
2621 struct net *net = vxlan->net;
2622 struct vxlan_net *vn = net_generic(net, vxlan_net_id);
2623 __be16 port = vxlan->dst_port;
2624 struct vxlan_sock *nvs;
2625
2626 nvs = vxlan_sock_add(net, port, vxlan_rcv, NULL, false, vxlan->flags);
2627 spin_lock(&vn->sock_lock);
2628 if (!IS_ERR(nvs))
2629 vxlan_vs_add_dev(nvs, vxlan);
2630 spin_unlock(&vn->sock_lock);
2631
2632 dev_put(vxlan->dev);
2633}
2634
2635static int vxlan_newlink(struct net *src_net, struct net_device *dev, 2584static int vxlan_newlink(struct net *src_net, struct net_device *dev,
2636 struct nlattr *tb[], struct nlattr *data[]) 2585 struct nlattr *tb[], struct nlattr *data[])
2637{ 2586{