summaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/bcast.c4
-rw-r--r--net/tipc/bearer.c64
-rw-r--r--net/tipc/bearer.h10
-rw-r--r--net/tipc/core.c5
-rw-r--r--net/tipc/core.h3
-rw-r--r--net/tipc/node.c1
-rw-r--r--net/tipc/topsrv.c2
7 files changed, 88 insertions, 1 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 1336f3cdad38..34f3e5641438 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -406,8 +406,10 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts,
406 rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); 406 rc = tipc_bcast_xmit(net, pkts, cong_link_cnt);
407 } 407 }
408 408
409 if (dests->local) 409 if (dests->local) {
410 tipc_loopback_trace(net, &localq);
410 tipc_sk_mcast_rcv(net, &localq, &inputq); 411 tipc_sk_mcast_rcv(net, &localq, &inputq);
412 }
411exit: 413exit:
412 /* This queue should normally be empty by now */ 414 /* This queue should normally be empty by now */
413 __skb_queue_purge(pkts); 415 __skb_queue_purge(pkts);
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index a809c0ec8d15..0214aa1c4427 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -389,6 +389,11 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
389 dev_put(dev); 389 dev_put(dev);
390 return -EINVAL; 390 return -EINVAL;
391 } 391 }
392 if (dev == net->loopback_dev) {
393 dev_put(dev);
394 pr_info("Enabling <%s> not permitted\n", b->name);
395 return -EINVAL;
396 }
392 397
393 /* Autoconfigure own node identity if needed */ 398 /* Autoconfigure own node identity if needed */
394 if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { 399 if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) {
@@ -674,6 +679,65 @@ void tipc_bearer_stop(struct net *net)
674 } 679 }
675} 680}
676 681
682void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts)
683{
684 struct net_device *dev = net->loopback_dev;
685 struct sk_buff *skb, *_skb;
686 int exp;
687
688 skb_queue_walk(pkts, _skb) {
689 skb = pskb_copy(_skb, GFP_ATOMIC);
690 if (!skb)
691 continue;
692
693 exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb));
694 if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) {
695 kfree_skb(skb);
696 continue;
697 }
698
699 skb_reset_network_header(skb);
700 dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr,
701 dev->dev_addr, skb->len);
702 skb->dev = dev;
703 skb->pkt_type = PACKET_HOST;
704 skb->ip_summed = CHECKSUM_UNNECESSARY;
705 skb->protocol = eth_type_trans(skb, dev);
706 netif_rx_ni(skb);
707 }
708}
709
710static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev,
711 struct packet_type *pt, struct net_device *od)
712{
713 consume_skb(skb);
714 return NET_RX_SUCCESS;
715}
716
717int tipc_attach_loopback(struct net *net)
718{
719 struct net_device *dev = net->loopback_dev;
720 struct tipc_net *tn = tipc_net(net);
721
722 if (!dev)
723 return -ENODEV;
724
725 dev_hold(dev);
726 tn->loopback_pt.dev = dev;
727 tn->loopback_pt.type = htons(ETH_P_TIPC);
728 tn->loopback_pt.func = tipc_loopback_rcv_pkt;
729 dev_add_pack(&tn->loopback_pt);
730 return 0;
731}
732
733void tipc_detach_loopback(struct net *net)
734{
735 struct tipc_net *tn = tipc_net(net);
736
737 dev_remove_pack(&tn->loopback_pt);
738 dev_put(net->loopback_dev);
739}
740
677/* Caller should hold rtnl_lock to protect the bearer */ 741/* Caller should hold rtnl_lock to protect the bearer */
678static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, 742static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
679 struct tipc_bearer *bearer, int nlflags) 743 struct tipc_bearer *bearer, int nlflags)
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 7f4c569594a5..ea0f3c49cbed 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -232,6 +232,16 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
232 struct tipc_media_addr *dst); 232 struct tipc_media_addr *dst);
233void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, 233void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
234 struct sk_buff_head *xmitq); 234 struct sk_buff_head *xmitq);
235void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts);
236int tipc_attach_loopback(struct net *net);
237void tipc_detach_loopback(struct net *net);
238
239static inline void tipc_loopback_trace(struct net *net,
240 struct sk_buff_head *pkts)
241{
242 if (unlikely(dev_nit_active(net->loopback_dev)))
243 tipc_clone_to_loopback(net, pkts);
244}
235 245
236/* check if device MTU is too low for tipc headers */ 246/* check if device MTU is too low for tipc headers */
237static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) 247static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve)
diff --git a/net/tipc/core.c b/net/tipc/core.c
index c8370722f0bb..23cb379a93d6 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -82,6 +82,10 @@ static int __net_init tipc_init_net(struct net *net)
82 if (err) 82 if (err)
83 goto out_bclink; 83 goto out_bclink;
84 84
85 err = tipc_attach_loopback(net);
86 if (err)
87 goto out_bclink;
88
85 return 0; 89 return 0;
86 90
87out_bclink: 91out_bclink:
@@ -94,6 +98,7 @@ out_sk_rht:
94 98
95static void __net_exit tipc_exit_net(struct net *net) 99static void __net_exit tipc_exit_net(struct net *net)
96{ 100{
101 tipc_detach_loopback(net);
97 tipc_net_stop(net); 102 tipc_net_stop(net);
98 tipc_bcast_stop(net); 103 tipc_bcast_stop(net);
99 tipc_nametbl_stop(net); 104 tipc_nametbl_stop(net);
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 7a68e1b6a066..60d829581068 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -125,6 +125,9 @@ struct tipc_net {
125 125
126 /* Cluster capabilities */ 126 /* Cluster capabilities */
127 u16 capabilities; 127 u16 capabilities;
128
129 /* Tracing of node internal messages */
130 struct packet_type loopback_pt;
128}; 131};
129 132
130static inline struct tipc_net *tipc_net(struct net *net) 133static inline struct tipc_net *tipc_net(struct net *net)
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 7ca019001f7c..1bdcf0fc1a4d 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1443,6 +1443,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list,
1443 int rc; 1443 int rc;
1444 1444
1445 if (in_own_node(net, dnode)) { 1445 if (in_own_node(net, dnode)) {
1446 tipc_loopback_trace(net, list);
1446 tipc_sk_rcv(net, list); 1447 tipc_sk_rcv(net, list);
1447 return 0; 1448 return 0;
1448 } 1449 }
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c
index ca8ac96d22a9..3a12fc18239b 100644
--- a/net/tipc/topsrv.c
+++ b/net/tipc/topsrv.c
@@ -40,6 +40,7 @@
40#include "socket.h" 40#include "socket.h"
41#include "addr.h" 41#include "addr.h"
42#include "msg.h" 42#include "msg.h"
43#include "bearer.h"
43#include <net/sock.h> 44#include <net/sock.h>
44#include <linux/module.h> 45#include <linux/module.h>
45 46
@@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt)
608 memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); 609 memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt));
609 skb_queue_head_init(&evtq); 610 skb_queue_head_init(&evtq);
610 __skb_queue_tail(&evtq, skb); 611 __skb_queue_tail(&evtq, skb);
612 tipc_loopback_trace(net, &evtq);
611 tipc_sk_rcv(net, &evtq); 613 tipc_sk_rcv(net, &evtq);
612} 614}
613 615