aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2016-08-26 04:52:53 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-27 00:38:41 -0400
commitef20cd4dd1633987bcf46ac34ace2c8af212361f (patch)
tree016eff3257434db4f8ec7f8270d1dc981836c9a8 /net/tipc
parent1ca73e3fa12531bbbc854329cd02a887f986a02a (diff)
tipc: introduce UDP replicast
This patch introduces UDP replicast. A concept where we emulate multicast by sending multiple unicast messages to configured peers. The purpose of replicast is mainly to be able to use TIPC in cloud environments where IP multicast is disabled. Using replicas to unicast multicast messages is costly as we have to copy each skb and send the copies individually. Signed-off-by: Richard Alpe <richard.alpe@ericsson.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/bearer.c44
-rw-r--r--net/tipc/bearer.h1
-rw-r--r--net/tipc/netlink.c5
-rw-r--r--net/tipc/udp_media.c118
-rw-r--r--net/tipc/udp_media.h44
5 files changed, 200 insertions, 12 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 28056fa8f77a..d7b442dd6669 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -42,6 +42,7 @@
42#include "monitor.h" 42#include "monitor.h"
43#include "bcast.h" 43#include "bcast.h"
44#include "netlink.h" 44#include "netlink.h"
45#include "udp_media.h"
45 46
46#define MAX_ADDR_STR 60 47#define MAX_ADDR_STR 60
47 48
@@ -897,6 +898,49 @@ int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info)
897 return 0; 898 return 0;
898} 899}
899 900
901int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info)
902{
903 int err;
904 char *name;
905 struct tipc_bearer *b;
906 struct nlattr *attrs[TIPC_NLA_BEARER_MAX + 1];
907 struct net *net = sock_net(skb->sk);
908
909 if (!info->attrs[TIPC_NLA_BEARER])
910 return -EINVAL;
911
912 err = nla_parse_nested(attrs, TIPC_NLA_BEARER_MAX,
913 info->attrs[TIPC_NLA_BEARER],
914 tipc_nl_bearer_policy);
915 if (err)
916 return err;
917
918 if (!attrs[TIPC_NLA_BEARER_NAME])
919 return -EINVAL;
920 name = nla_data(attrs[TIPC_NLA_BEARER_NAME]);
921
922 rtnl_lock();
923 b = tipc_bearer_find(net, name);
924 if (!b) {
925 rtnl_unlock();
926 return -EINVAL;
927 }
928
929#ifdef CONFIG_TIPC_MEDIA_UDP
930 if (attrs[TIPC_NLA_BEARER_UDP_OPTS]) {
931 err = tipc_udp_nl_bearer_add(b,
932 attrs[TIPC_NLA_BEARER_UDP_OPTS]);
933 if (err) {
934 rtnl_unlock();
935 return err;
936 }
937 }
938#endif
939 rtnl_unlock();
940
941 return 0;
942}
943
900int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) 944int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
901{ 945{
902 int err; 946 int err;
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 83a9abbfe32c..78892e2f53e3 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -181,6 +181,7 @@ int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info);
181int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb); 181int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb);
182int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info); 182int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info);
183int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info); 183int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info);
184int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info);
184 185
185int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb); 186int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb);
186int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info); 187int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info);
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 2718de667828..3122f21ca979 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -161,6 +161,11 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
161 .policy = tipc_nl_policy, 161 .policy = tipc_nl_policy,
162 }, 162 },
163 { 163 {
164 .cmd = TIPC_NL_BEARER_ADD,
165 .doit = tipc_nl_bearer_add,
166 .policy = tipc_nl_policy,
167 },
168 {
164 .cmd = TIPC_NL_BEARER_SET, 169 .cmd = TIPC_NL_BEARER_SET,
165 .doit = tipc_nl_bearer_set, 170 .doit = tipc_nl_bearer_set,
166 .policy = tipc_nl_policy, 171 .policy = tipc_nl_policy,
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index b8ec1a18241e..6b938cc15daf 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -49,6 +49,7 @@
49#include "core.h" 49#include "core.h"
50#include "bearer.h" 50#include "bearer.h"
51#include "netlink.h" 51#include "netlink.h"
52#include "msg.h"
52 53
53/* IANA assigned UDP port */ 54/* IANA assigned UDP port */
54#define UDP_PORT_DEFAULT 6118 55#define UDP_PORT_DEFAULT 6118
@@ -70,6 +71,13 @@ struct udp_media_addr {
70 }; 71 };
71}; 72};
72 73
74/* struct udp_replicast - container for UDP remote addresses */
75struct udp_replicast {
76 struct udp_media_addr addr;
77 struct rcu_head rcu;
78 struct list_head list;
79};
80
73/** 81/**
74 * struct udp_bearer - ip/udp bearer data structure 82 * struct udp_bearer - ip/udp bearer data structure
75 * @bearer: associated generic tipc bearer 83 * @bearer: associated generic tipc bearer
@@ -82,6 +90,7 @@ struct udp_bearer {
82 struct socket *ubsock; 90 struct socket *ubsock;
83 u32 ifindex; 91 u32 ifindex;
84 struct work_struct work; 92 struct work_struct work;
93 struct udp_replicast rcast;
85}; 94};
86 95
87static int tipc_udp_is_mcast_addr(struct udp_media_addr *addr) 96static int tipc_udp_is_mcast_addr(struct udp_media_addr *addr)
@@ -203,29 +212,75 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
203{ 212{
204 struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value; 213 struct udp_media_addr *src = (struct udp_media_addr *)&b->addr.value;
205 struct udp_media_addr *dst = (struct udp_media_addr *)&addr->value; 214 struct udp_media_addr *dst = (struct udp_media_addr *)&addr->value;
215 struct udp_replicast *rcast;
206 struct udp_bearer *ub; 216 struct udp_bearer *ub;
207 int err = 0; 217 int err = 0;
208 218
209 if (skb_headroom(skb) < UDP_MIN_HEADROOM) { 219 if (skb_headroom(skb) < UDP_MIN_HEADROOM) {
210 err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC); 220 err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC);
211 if (err) 221 if (err)
212 goto tx_error; 222 goto out;
213 } 223 }
214 224
215 skb_set_inner_protocol(skb, htons(ETH_P_TIPC)); 225 skb_set_inner_protocol(skb, htons(ETH_P_TIPC));
216 ub = rcu_dereference_rtnl(b->media_ptr); 226 ub = rcu_dereference_rtnl(b->media_ptr);
217 if (!ub) { 227 if (!ub) {
218 err = -ENODEV; 228 err = -ENODEV;
219 goto tx_error; 229 goto out;
220 } 230 }
221 231
222 return tipc_udp_xmit(net, skb, ub, src, dst); 232 if (!addr->broadcast || list_empty(&ub->rcast.list))
233 return tipc_udp_xmit(net, skb, ub, src, dst);
223 234
224tx_error: 235 /* Replicast, send an skb to each configured IP address */
236 list_for_each_entry_rcu(rcast, &ub->rcast.list, list) {
237 struct sk_buff *_skb;
238
239 _skb = pskb_copy(skb, GFP_ATOMIC);
240 if (!_skb) {
241 err = -ENOMEM;
242 goto out;
243 }
244
245 err = tipc_udp_xmit(net, _skb, ub, src, &rcast->addr);
246 if (err) {
247 kfree_skb(_skb);
248 goto out;
249 }
250 }
251 err = 0;
252out:
225 kfree_skb(skb); 253 kfree_skb(skb);
226 return err; 254 return err;
227} 255}
228 256
257static int tipc_udp_rcast_add(struct tipc_bearer *b,
258 struct udp_media_addr *addr)
259{
260 struct udp_replicast *rcast;
261 struct udp_bearer *ub;
262
263 ub = rcu_dereference_rtnl(b->media_ptr);
264 if (!ub)
265 return -ENODEV;
266
267 rcast = kmalloc(sizeof(*rcast), GFP_ATOMIC);
268 if (!rcast)
269 return -ENOMEM;
270
271 memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr));
272
273 if (ntohs(addr->proto) == ETH_P_IP)
274 pr_info("New replicast peer: %pI4\n", &rcast->addr.ipv4);
275#if IS_ENABLED(CONFIG_IPV6)
276 else if (ntohs(addr->proto) == ETH_P_IPV6)
277 pr_info("New replicast peer: %pI6\n", &rcast->addr.ipv6);
278#endif
279
280 list_add_rcu(&rcast->list, &ub->rcast.list);
281 return 0;
282}
283
229/* tipc_udp_recv - read data from bearer socket */ 284/* tipc_udp_recv - read data from bearer socket */
230static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb) 285static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb)
231{ 286{
@@ -320,6 +375,32 @@ static int tipc_parse_udp_addr(struct nlattr *nla, struct udp_media_addr *addr,
320 return -EADDRNOTAVAIL; 375 return -EADDRNOTAVAIL;
321} 376}
322 377
378int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr)
379{
380 int err;
381 struct udp_media_addr addr = {0};
382 struct nlattr *opts[TIPC_NLA_UDP_MAX + 1];
383 struct udp_media_addr *dst;
384
385 if (nla_parse_nested(opts, TIPC_NLA_UDP_MAX, attr, tipc_nl_udp_policy))
386 return -EINVAL;
387
388 if (!opts[TIPC_NLA_UDP_REMOTE])
389 return -EINVAL;
390
391 err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], &addr, NULL);
392 if (err)
393 return err;
394
395 dst = (struct udp_media_addr *)&b->bcast_addr.value;
396 if (tipc_udp_is_mcast_addr(dst)) {
397 pr_err("Can't add remote ip to TIPC UDP multicast bearer\n");
398 return -EINVAL;
399 }
400
401 return tipc_udp_rcast_add(b, &addr);
402}
403
323/** 404/**
324 * tipc_udp_enable - callback to create a new udp bearer instance 405 * tipc_udp_enable - callback to create a new udp bearer instance
325 * @net: network namespace 406 * @net: network namespace
@@ -334,7 +415,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
334{ 415{
335 int err = -EINVAL; 416 int err = -EINVAL;
336 struct udp_bearer *ub; 417 struct udp_bearer *ub;
337 struct udp_media_addr *remote; 418 struct udp_media_addr remote = {0};
338 struct udp_media_addr local = {0}; 419 struct udp_media_addr local = {0};
339 struct udp_port_cfg udp_conf = {0}; 420 struct udp_port_cfg udp_conf = {0};
340 struct udp_tunnel_sock_cfg tuncfg = {NULL}; 421 struct udp_tunnel_sock_cfg tuncfg = {NULL};
@@ -344,6 +425,8 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
344 if (!ub) 425 if (!ub)
345 return -ENOMEM; 426 return -ENOMEM;
346 427
428 INIT_LIST_HEAD(&ub->rcast.list);
429
347 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) 430 if (!attrs[TIPC_NLA_BEARER_UDP_OPTS])
348 goto err; 431 goto err;
349 432
@@ -362,9 +445,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
362 if (err) 445 if (err)
363 goto err; 446 goto err;
364 447
365 remote = (struct udp_media_addr *)&b->bcast_addr.value; 448 err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], &remote, NULL);
366 memset(remote, 0, sizeof(struct udp_media_addr));
367 err = tipc_parse_udp_addr(opts[TIPC_NLA_UDP_REMOTE], remote, NULL);
368 if (err) 449 if (err)
369 goto err; 450 goto err;
370 451
@@ -409,10 +490,17 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
409 tuncfg.encap_destroy = NULL; 490 tuncfg.encap_destroy = NULL;
410 setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg); 491 setup_udp_tunnel_sock(net, ub->ubsock, &tuncfg);
411 492
412 if (tipc_udp_is_mcast_addr(remote)) { 493 /**
413 if (enable_mcast(ub, remote)) 494 * The bcast media address port is used for all peers and the ip
414 goto err; 495 * is used if it's a multicast address.
415 } 496 */
497 memcpy(&b->bcast_addr.value, &remote, sizeof(remote));
498 if (tipc_udp_is_mcast_addr(&remote))
499 err = enable_mcast(ub, &remote);
500 else
501 err = tipc_udp_rcast_add(b, &remote);
502 if (err)
503 goto err;
416 504
417 return 0; 505 return 0;
418err: 506err:
@@ -424,6 +512,12 @@ err:
424static void cleanup_bearer(struct work_struct *work) 512static void cleanup_bearer(struct work_struct *work)
425{ 513{
426 struct udp_bearer *ub = container_of(work, struct udp_bearer, work); 514 struct udp_bearer *ub = container_of(work, struct udp_bearer, work);
515 struct udp_replicast *rcast, *tmp;
516
517 list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
518 list_del_rcu(&rcast->list);
519 kfree_rcu(rcast, rcu);
520 }
427 521
428 if (ub->ubsock) 522 if (ub->ubsock)
429 udp_tunnel_sock_release(ub->ubsock); 523 udp_tunnel_sock_release(ub->ubsock);
diff --git a/net/tipc/udp_media.h b/net/tipc/udp_media.h
new file mode 100644
index 000000000000..4dcb54880aa6
--- /dev/null
+++ b/net/tipc/udp_media.h
@@ -0,0 +1,44 @@
1/*
2 * net/tipc/udp_media.h: Include file for UDP bearer media
3 *
4 * Copyright (c) 1996-2006, 2013-2016, Ericsson AB
5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifdef CONFIG_TIPC_MEDIA_UDP
38#ifndef _TIPC_UDP_MEDIA_H
39#define _TIPC_UDP_MEDIA_H
40
41int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr);
42
43#endif
44#endif