diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 4 | ||||
-rw-r--r-- | net/tipc/bearer.c | 64 | ||||
-rw-r--r-- | net/tipc/bearer.h | 10 | ||||
-rw-r--r-- | net/tipc/core.c | 5 | ||||
-rw-r--r-- | net/tipc/core.h | 3 | ||||
-rw-r--r-- | net/tipc/node.c | 1 | ||||
-rw-r--r-- | net/tipc/topsrv.c | 2 |
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 | } | ||
411 | exit: | 413 | exit: |
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 | ||
682 | void 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 | |||
710 | static 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 | |||
717 | int 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 | |||
733 | void 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 */ |
678 | static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, | 742 | static 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); |
233 | void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, | 233 | void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, |
234 | struct sk_buff_head *xmitq); | 234 | struct sk_buff_head *xmitq); |
235 | void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); | ||
236 | int tipc_attach_loopback(struct net *net); | ||
237 | void tipc_detach_loopback(struct net *net); | ||
238 | |||
239 | static 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 */ |
237 | static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve) | 247 | static 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 | ||
87 | out_bclink: | 91 | out_bclink: |
@@ -94,6 +98,7 @@ out_sk_rht: | |||
94 | 98 | ||
95 | static void __net_exit tipc_exit_net(struct net *net) | 99 | static 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 | ||
130 | static inline struct tipc_net *tipc_net(struct net *net) | 133 | static 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 | ||