From: John R. <joh...@de...> - 2019-06-14 01:58:37
|
Since node internal messages are passed directly to socket it is not possible to observe this message exchange via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is turned on/off by enabling/disabling the loopback "bearer" "eth:lo". Signed-off-by: John Rutherford <joh...@de...> Signed-off-by: Jon Maloy <jon...@er...> --- net/tipc/bcast.c | 5 +++- net/tipc/bearer.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 3 +++ net/tipc/core.c | 5 +++- net/tipc/core.h | 9 ++++++++ net/tipc/netlink.c | 2 +- net/tipc/node.c | 2 ++ net/tipc/topsrv.c | 3 +++ 8 files changed, 93 insertions(+), 3 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..db40129 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -406,8 +406,11 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + if (unlikely(tipc_loopback_trace(net))) + tipc_clone_to_loopback(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..27b4fd7 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(name, "eth:lo")) { + tipc_net(net)->loopback_trace = false; + pr_info("Disabled packet tracing on loopback interface\n"); + return 0; + } + bearer = tipc_bearer_find(net, name); if (!bearer) return -EINVAL; @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(bearer, "eth:lo")) { + tipc_net(net)->loopback_trace = true; + pr_info("Enabled packet tracing on loopback interface\n"); + return 0; + } + if (attrs[TIPC_NLA_BEARER_DOMAIN]) domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) return err; } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(xmitq, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + skb_reset_network_header(skb); + skb->dev = dev; + skb->protocol = htons(ETH_P_TIPC); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + dev_queue_xmit(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + tn->loopback_trace = false; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + static int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct tipc_media *media, int nlflags) { diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) err = tipc_bcast_init(net); if (err) goto out_bclink; - + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; return 0; out_bclink: @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..de164ac 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -125,6 +125,10 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; + bool loopback_trace; }; static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 +156,11 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) return tipc_net(net)->topsrv; } +static inline bool tipc_loopback_trace(struct net *net) +{ + return tipc_net(net)->loopback_trace; +} + static inline unsigned int tipc_hashfn(u32 addr) { return addr & (NODE_HTABLE_SIZE - 1); diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 99bd166..d6165ad 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -261,7 +261,7 @@ struct genl_family tipc_genl_family __ro_after_init = { .version = TIPC_GENL_V2_VERSION, .hdrsize = 0, .maxattr = TIPC_NLA_MAX, - .policy = tipc_nl_policy, + .policy = tipc_nl_policy, .netnsok = true, .module = THIS_MODULE, .ops = tipc_genl_v2_ops, diff --git a/net/tipc/node.c b/net/tipc/node.c index 9e106d3..415d02d 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1439,6 +1439,8 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, int rc; if (in_own_node(net, dnode)) { + if (unlikely(tipc_loopback_trace(net))) + tipc_clone_to_loopback(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..37f07e7 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include <net/sock.h> #include <linux/module.h> @@ -608,6 +609,8 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + if (unlikely(tipc_loopback_trace(net))) + tipc_clone_to_loopback(net, &evtq); tipc_sk_rcv(net, &evtq); } -- 2.11.0 --- This email has been checked for viruses by AVG. https://www.avg.com |
From: Jon M. <jon...@er...> - 2019-06-14 13:07:28
|
Hi John, When looking at this again, I think we can make another small improvement, which will make the code look a little bit nicer: + static inline void tipc_loopback_trace(struct net *net, struct sk_buff_head* pkts) +{ + if (unlikely(tipc_net(net)->loopback_trace) + tipc_clone_to_loopback(net, pkts); +} This will result in the same binary code from the compiler, but we don't need to make the call conditional directly in the data path. Otherwise this is still ok with me. Just remember to put [net-next] instead of [PATCH] in the patch header, and run scripts/checkpatch on it. ///jon > -----Original Message----- > From: John Rutherford <joh...@de...> > Sent: 13-Jun-19 21:58 > To: tip...@li... > Subject: [tipc-discussion] [PATCH] tipc: add loopback device tracking > > Since node internal messages are passed directly to socket it is not possible to > observe > > this message exchange via tcpdump or wireshark. > > > > We now remedy this by making it possible to clone such messages and send > the clones to the > > loopback interface. The clones are dropped at reception and have no > functional role except > > making the traffic visible. > > > > The feature is turned on/off by enabling/disabling the loopback "bearer" > "eth:lo". > > Signed-off-by: John Rutherford <joh...@de...> > > Signed-off-by: Jon Maloy <jon...@er...> > > --- > > net/tipc/bcast.c | 5 +++- > > net/tipc/bearer.c | 67 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > net/tipc/bearer.h | 3 +++ > > net/tipc/core.c | 5 +++- > > net/tipc/core.h | 9 ++++++++ > > net/tipc/netlink.c | 2 +- > > net/tipc/node.c | 2 ++ > > net/tipc/topsrv.c | 3 +++ > > 8 files changed, 93 insertions(+), 3 deletions(-) > > > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c > > index 6c997d4..db40129 100644 > > --- a/net/tipc/bcast.c > > +++ b/net/tipc/bcast.c > > @@ -406,8 +406,11 @@ int tipc_mcast_xmit(struct net *net, struct > sk_buff_head *pkts, > > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > > } > > - if (dests->local) > > + if (dests->local) { > > + if (unlikely(tipc_loopback_trace(net))) > > + > + tipc_clone_to_loopback(net, > &localq); > > tipc_sk_mcast_rcv(net, &localq, &inputq); > > + } > > exit: > > /* This queue should normally be empty by now */ > > __skb_queue_purge(pkts); > > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c > > index 2bed658..27b4fd7 100644 > > --- a/net/tipc/bearer.c > > +++ b/net/tipc/bearer.c > > @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, > struct genl_info *info) > > name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(name, "eth:lo")) { > > + tipc_net(net)->loopback_trace = false; > > + pr_info("Disabled packet tracing on > + loopback > interface\n"); > > + return 0; > > + } > > + > > bearer = tipc_bearer_find(net, name); > > if (!bearer) > > return -EINVAL; > > @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, > struct genl_info *info) > > bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(bearer, "eth:lo")) { > > + tipc_net(net)->loopback_trace = true; > > + pr_info("Enabled packet tracing on > + loopback > interface\n"); > > + return 0; > > + } > > + > > if (attrs[TIPC_NLA_BEARER_DOMAIN]) > > domain = > nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); > > @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct > genl_info *info) > > return err; > > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > +*xmitq) > > +{ > > + struct net_device *dev = net->loopback_dev; > > + struct sk_buff *skb, *_skb; > > + int exp; > > + > > + skb_queue_walk(xmitq, _skb) { > > + skb = pskb_copy(_skb, GFP_ATOMIC); > > + if (!skb) > > + continue; > > + exp = SKB_DATA_ALIGN(dev->hard_header_len > + - > skb_headroom(skb)); > > + if (exp > 0 && pskb_expand_head(skb, exp, > + 0, > GFP_ATOMIC)) { > > + kfree_skb(skb); > > + continue; > > + } > > + skb_reset_network_header(skb); > > + skb->dev = dev; > > + skb->protocol = htons(ETH_P_TIPC); > > + dev_hard_header(skb, dev, ETH_P_TIPC, > dev->dev_addr, > > + > + dev->dev_addr, > skb->len); > > + dev_queue_xmit(skb); > > + } > > +} > > + > > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device > *dev, > > + struct > packet_type *pt, struct net_device *od) > > +{ > > + consume_skb(skb); > > + return NET_RX_SUCCESS; > > +} > > + > > +int tipc_attach_loopback(struct net *net) > > +{ > > + struct net_device *dev = net->loopback_dev; > > + struct tipc_net *tn = tipc_net(net); > > + > > + if (!dev) > > + return -ENODEV; > > + dev_hold(dev); > > + tn->loopback_pt.dev = dev; > > + tn->loopback_pt.type = htons(ETH_P_TIPC); > > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > > + tn->loopback_trace = false; > > + dev_add_pack(&tn->loopback_pt); > > + return 0; > > +} > > + > > +void tipc_detach_loopback(struct net *net) > > +{ > > + struct tipc_net *tn = tipc_net(net); > > + > > + dev_remove_pack(&tn->loopback_pt); > > + dev_put(net->loopback_dev); > > +} > > + > > static int __tipc_nl_add_media(struct tipc_nl_msg *msg, > > struct tipc_media *media, int nlflags) > > { > > diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h > > index 7f4c569..ef7fad9 100644 > > --- a/net/tipc/bearer.h > > +++ b/net/tipc/bearer.h > > @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 > bearer_id, > > struct tipc_media_addr *dst); > > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > > struct sk_buff_head *xmitq); > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > +*xmitq); > > +int tipc_attach_loopback(struct net *net); > > +void tipc_detach_loopback(struct net *net); > > /* check if device MTU is too low for tipc headers */ > > 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 ed536c0..1867687 100644 > > --- a/net/tipc/core.c > > +++ b/net/tipc/core.c > > @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) > > err = tipc_bcast_init(net); > > if (err) > > goto out_bclink; > > - > > + err = tipc_attach_loopback(net); > > + if (err) > > + goto out_bclink; > > return 0; > > out_bclink: > > @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) > > { > > + tipc_detach_loopback(net); > > tipc_net_stop(net); > > tipc_bcast_stop(net); > > tipc_nametbl_stop(net); > > diff --git a/net/tipc/core.h b/net/tipc/core.h > > index 7a68e1b..de164ac 100644 > > --- a/net/tipc/core.h > > +++ b/net/tipc/core.h > > @@ -125,6 +125,10 @@ struct tipc_net { > > /* Cluster capabilities */ > > u16 capabilities; > > + > > + /* Tracing of node internal messages */ > > + struct packet_type loopback_pt; > > + bool loopback_trace; > > }; > > static inline struct tipc_net *tipc_net(struct net *net) > > @@ -152,6 +156,11 @@ static inline struct tipc_topsrv *tipc_topsrv(struct > net *net) > > return tipc_net(net)->topsrv; > > } > > +static inline bool tipc_loopback_trace(struct net *net) > > +{ > > + return tipc_net(net)->loopback_trace; > > +} > > + > > static inline unsigned int tipc_hashfn(u32 addr) > > { > > return addr & (NODE_HTABLE_SIZE - 1); > > diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c > > index 99bd166..d6165ad 100644 > > --- a/net/tipc/netlink.c > > +++ b/net/tipc/netlink.c > > @@ -261,7 +261,7 @@ struct genl_family tipc_genl_family __ro_after_init = > { > > .version = TIPC_GENL_V2_VERSION, > > .hdrsize = 0, > > .maxattr = TIPC_NLA_MAX, > > - .policy = tipc_nl_policy, > > + .policy = tipc_nl_policy, > > .netnsok = true, > > .module = THIS_MODULE, > > .ops = tipc_genl_v2_ops, > > diff --git a/net/tipc/node.c b/net/tipc/node.c > > index 9e106d3..415d02d 100644 > > --- a/net/tipc/node.c > > +++ b/net/tipc/node.c > > @@ -1439,6 +1439,8 @@ int tipc_node_xmit(struct net *net, struct > sk_buff_head *list, > > int rc; > > if (in_own_node(net, dnode)) { > > + if (unlikely(tipc_loopback_trace(net))) > > + > + tipc_clone_to_loopback(net, > list); > > tipc_sk_rcv(net, list); > > return 0; > > } > > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c > > index f345662..37f07e7 100644 > > --- a/net/tipc/topsrv.c > > +++ b/net/tipc/topsrv.c > > @@ -40,6 +40,7 @@ > > #include "socket.h" > > #include "addr.h" > > #include "msg.h" > > +#include "bearer.h" > > #include <net/sock.h> > > #include <linux/module.h> > > @@ -608,6 +609,8 @@ static void tipc_topsrv_kern_evt(struct net *net, > struct tipc_event *evt) > > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > > skb_queue_head_init(&evtq); > > __skb_queue_tail(&evtq, skb); > > + if (unlikely(tipc_loopback_trace(net))) > > + tipc_clone_to_loopback(net, &evtq); > > tipc_sk_rcv(net, &evtq); > > } > > -- > > 2.11.0 > > > > > > --- > This email has been checked for viruses by AVG. > https://www.avg.com > > _______________________________________________ > tipc-discussion mailing list > tip...@li... > https://lists.sourceforge.net/lists/listinfo/tipc-discussion |
From: Ying X. <yin...@wi...> - 2019-06-16 07:46:02
|
Hi John, Can you please submit the patch with "git send-email" command again? The patch has been totally messed under Linux environment. Thanks, Ying On 6/14/19 9:58 AM, John Rutherford wrote: > Since node internal messages are passed directly to socket it is not > possible to observe > > this message exchange via tcpdump or wireshark. > > > > We now remedy this by making it possible to clone such messages and send the > clones to the > > loopback interface. The clones are dropped at reception and have no > functional role except > > making the traffic visible. > > > > The feature is turned on/off by enabling/disabling the loopback "bearer" > "eth:lo". > > Signed-off-by: John Rutherford <joh...@de...> > > Signed-off-by: Jon Maloy <jon...@er...> > > --- > > net/tipc/bcast.c | 5 +++- > > net/tipc/bearer.c | 67 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > net/tipc/bearer.h | 3 +++ > > net/tipc/core.c | 5 +++- > > net/tipc/core.h | 9 ++++++++ > > net/tipc/netlink.c | 2 +- > > net/tipc/node.c | 2 ++ > > net/tipc/topsrv.c | 3 +++ > > 8 files changed, 93 insertions(+), 3 deletions(-) > > > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c > > index 6c997d4..db40129 100644 > > --- a/net/tipc/bcast.c > > +++ b/net/tipc/bcast.c > > @@ -406,8 +406,11 @@ int tipc_mcast_xmit(struct net *net, struct > sk_buff_head *pkts, > > rc = tipc_bcast_xmit(net, > pkts, cong_link_cnt); > > } > > - if (dests->local) > > + if (dests->local) { > > + if (unlikely(tipc_loopback_trace(net))) > > + tipc_clone_to_loopback(net, > &localq); > > tipc_sk_mcast_rcv(net, &localq, &inputq); > > + } > > exit: > > /* This queue should normally be empty by now */ > > __skb_queue_purge(pkts); > > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c > > index 2bed658..27b4fd7 100644 > > --- a/net/tipc/bearer.c > > +++ b/net/tipc/bearer.c > > @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, > struct genl_info *info) > > name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(name, "eth:lo")) { > > + tipc_net(net)->loopback_trace = false; > > + pr_info("Disabled packet tracing on loopback > interface\n"); > > + return 0; > > + } > > + > > bearer = tipc_bearer_find(net, name); > > if (!bearer) > > return -EINVAL; > > @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct > genl_info *info) > > bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(bearer, "eth:lo")) { > > + tipc_net(net)->loopback_trace = true; > > + pr_info("Enabled packet tracing on loopback > interface\n"); > > + return 0; > > + } > > + > > if (attrs[TIPC_NLA_BEARER_DOMAIN]) > > domain = > nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); > > @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct > genl_info *info) > > return err; > > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) > > +{ > > + struct net_device *dev = net->loopback_dev; > > + struct sk_buff *skb, *_skb; > > + int exp; > > + > > + skb_queue_walk(xmitq, _skb) { > > + skb = pskb_copy(_skb, GFP_ATOMIC); > > + if (!skb) > > + continue; > > + exp = SKB_DATA_ALIGN(dev->hard_header_len - > skb_headroom(skb)); > > + if (exp > 0 && pskb_expand_head(skb, exp, 0, > GFP_ATOMIC)) { > > + kfree_skb(skb); > > + continue; > > + } > > + skb_reset_network_header(skb); > > + skb->dev = dev; > > + skb->protocol = htons(ETH_P_TIPC); > > + dev_hard_header(skb, dev, ETH_P_TIPC, > dev->dev_addr, > > + dev->dev_addr, > skb->len); > > + dev_queue_xmit(skb); > > + } > > +} > > + > > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device > *dev, > > + struct > packet_type *pt, struct net_device *od) > > +{ > > + consume_skb(skb); > > + return NET_RX_SUCCESS; > > +} > > + > > +int tipc_attach_loopback(struct net *net) > > +{ > > + struct net_device *dev = net->loopback_dev; > > + struct tipc_net *tn = tipc_net(net); > > + > > + if (!dev) > > + return -ENODEV; > > + dev_hold(dev); > > + tn->loopback_pt.dev = dev; > > + tn->loopback_pt.type = htons(ETH_P_TIPC); > > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > > + tn->loopback_trace = false; > > + dev_add_pack(&tn->loopback_pt); > > + return 0; > > +} > > + > > +void tipc_detach_loopback(struct net *net) > > +{ > > + struct tipc_net *tn = tipc_net(net); > > + > > + dev_remove_pack(&tn->loopback_pt); > > + dev_put(net->loopback_dev); > > +} > > + > > static int __tipc_nl_add_media(struct tipc_nl_msg *msg, > > struct tipc_media > *media, int nlflags) > > { > > diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h > > index 7f4c569..ef7fad9 100644 > > --- a/net/tipc/bearer.h > > +++ b/net/tipc/bearer.h > > @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, > > struct tipc_media_addr *dst); > > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > > struct sk_buff_head *xmitq); > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); > > +int tipc_attach_loopback(struct net *net); > > +void tipc_detach_loopback(struct net *net); > > /* check if device MTU is too low for tipc headers */ > > 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 ed536c0..1867687 100644 > > --- a/net/tipc/core.c > > +++ b/net/tipc/core.c > > @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) > > err = tipc_bcast_init(net); > > if (err) > > goto out_bclink; > > - > > + err = tipc_attach_loopback(net); > > + if (err) > > + goto out_bclink; > > return 0; > > out_bclink: > > @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) > > { > > + tipc_detach_loopback(net); > > tipc_net_stop(net); > > tipc_bcast_stop(net); > > tipc_nametbl_stop(net); > > diff --git a/net/tipc/core.h b/net/tipc/core.h > > index 7a68e1b..de164ac 100644 > > --- a/net/tipc/core.h > > +++ b/net/tipc/core.h > > @@ -125,6 +125,10 @@ struct tipc_net { > > /* Cluster capabilities */ > > u16 capabilities; > > + > > + /* Tracing of node internal messages */ > > + struct packet_type loopback_pt; > > + bool loopback_trace; > > }; > > static inline struct tipc_net *tipc_net(struct net *net) > > @@ -152,6 +156,11 @@ static inline struct tipc_topsrv *tipc_topsrv(struct > net *net) > > return tipc_net(net)->topsrv; > > } > > +static inline bool tipc_loopback_trace(struct net *net) > > +{ > > + return tipc_net(net)->loopback_trace; > > +} > > + > > static inline unsigned int tipc_hashfn(u32 addr) > > { > > return addr & (NODE_HTABLE_SIZE - 1); > > diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c > > index 99bd166..d6165ad 100644 > > --- a/net/tipc/netlink.c > > +++ b/net/tipc/netlink.c > > @@ -261,7 +261,7 @@ struct genl_family tipc_genl_family __ro_after_init = { > > .version = TIPC_GENL_V2_VERSION, > > .hdrsize = 0, > > .maxattr = TIPC_NLA_MAX, > > - .policy = tipc_nl_policy, > > + .policy = tipc_nl_policy, > > .netnsok = true, > > .module = THIS_MODULE, > > .ops = tipc_genl_v2_ops, > > diff --git a/net/tipc/node.c b/net/tipc/node.c > > index 9e106d3..415d02d 100644 > > --- a/net/tipc/node.c > > +++ b/net/tipc/node.c > > @@ -1439,6 +1439,8 @@ int tipc_node_xmit(struct net *net, struct > sk_buff_head *list, > > int rc; > > if (in_own_node(net, dnode)) { > > + if (unlikely(tipc_loopback_trace(net))) > > + tipc_clone_to_loopback(net, > list); > > tipc_sk_rcv(net, list); > > return 0; > > } > > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c > > index f345662..37f07e7 100644 > > --- a/net/tipc/topsrv.c > > +++ b/net/tipc/topsrv.c > > @@ -40,6 +40,7 @@ > > #include "socket.h" > > #include "addr.h" > > #include "msg.h" > > +#include "bearer.h" > > #include <net/sock.h> > > #include <linux/module.h> > > @@ -608,6 +609,8 @@ static void tipc_topsrv_kern_evt(struct net *net, struct > tipc_event *evt) > > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > > skb_queue_head_init(&evtq); > > __skb_queue_tail(&evtq, skb); > > + if (unlikely(tipc_loopback_trace(net))) > > + tipc_clone_to_loopback(net, &evtq); > > tipc_sk_rcv(net, &evtq); > > } > |
From: John R. <joh...@de...> - 2019-06-18 00:22:35
|
Since node internal messages are passed directly to socket it is not possible to observe this message exchange via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is turned on/off by enabling/disabling the loopback "bearer" "eth:lo". Signed-off-by: John Rutherford <joh...@de...> --- net/tipc/bcast.c | 4 +++- net/tipc/bearer.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 3 +++ net/tipc/core.c | 5 +++- net/tipc/core.h | 12 ++++++++++ net/tipc/netlink.c | 2 +- net/tipc/node.c | 1 + net/tipc/topsrv.c | 2 ++ 8 files changed, 93 insertions(+), 3 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d 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, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + tipc_loopback_trace(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..27b4fd7 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(name, "eth:lo")) { + tipc_net(net)->loopback_trace = false; + pr_info("Disabled packet tracing on loopback interface\n"); + return 0; + } + bearer = tipc_bearer_find(net, name); if (!bearer) return -EINVAL; @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(bearer, "eth:lo")) { + tipc_net(net)->loopback_trace = true; + pr_info("Enabled packet tracing on loopback interface\n"); + return 0; + } + if (attrs[TIPC_NLA_BEARER_DOMAIN]) domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) return err; } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(xmitq, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + skb_reset_network_header(skb); + skb->dev = dev; + skb->protocol = htons(ETH_P_TIPC); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + dev_queue_xmit(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + tn->loopback_trace = false; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + static int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct tipc_media *media, int nlflags) { diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) err = tipc_bcast_init(net); if (err) goto out_bclink; - + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; return 0; out_bclink: @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..c1c2906 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -67,6 +67,7 @@ struct tipc_link; struct tipc_name_table; struct tipc_topsrv; struct tipc_monitor; +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); #define TIPC_MOD_VER "2.0.0" @@ -125,6 +126,10 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; + bool loopback_trace; }; static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) return tipc_net(net)->topsrv; } +static inline void tipc_loopback_trace(struct net *net, + struct sk_buff_head *pkts) +{ + if (unlikely(tipc_net(net)->loopback_trace)) + tipc_clone_to_loopback(net, pkts); +} + static inline unsigned int tipc_hashfn(u32 addr) { return addr & (NODE_HTABLE_SIZE - 1); diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 99bd166..d6165ad 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -261,7 +261,7 @@ struct genl_family tipc_genl_family __ro_after_init = { .version = TIPC_GENL_V2_VERSION, .hdrsize = 0, .maxattr = TIPC_NLA_MAX, - .policy = tipc_nl_policy, + .policy = tipc_nl_policy, .netnsok = true, .module = THIS_MODULE, .ops = tipc_genl_v2_ops, diff --git a/net/tipc/node.c b/net/tipc/node.c index 9e106d3..7e58831 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, int rc; if (in_own_node(net, dnode)) { + tipc_loopback_trace(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include <net/sock.h> #include <linux/module.h> @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + tipc_loopback_trace(net, &evtq); tipc_sk_rcv(net, &evtq); } -- 2.11.0 |
From: Erik H. <eri...@gm...> - 2019-06-18 05:14:15
|
Change in netlink.c unrelated to the commit //E On Tue, 18 Jun 2019, 02:23 John Rutherford, <joh...@de...> wrote: > Since node internal messages are passed directly to socket it is not > possible to observe this message exchange via tcpdump or wireshark. > > We now remedy this by making it possible to clone such messages and send > the clones to the loopback interface. The clones are dropped at reception > and have no functional role except making the traffic visible. > > The feature is turned on/off by enabling/disabling the loopback "bearer" > "eth:lo". > > Signed-off-by: John Rutherford <joh...@de...> > --- > net/tipc/bcast.c | 4 +++- > net/tipc/bearer.c | 67 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/tipc/bearer.h | 3 +++ > net/tipc/core.c | 5 +++- > net/tipc/core.h | 12 ++++++++++ > net/tipc/netlink.c | 2 +- > net/tipc/node.c | 1 + > net/tipc/topsrv.c | 2 ++ > 8 files changed, 93 insertions(+), 3 deletions(-) > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c > index 6c997d4..235331d 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, > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > } > > - if (dests->local) > + if (dests->local) { > + tipc_loopback_trace(net, &localq); > tipc_sk_mcast_rcv(net, &localq, &inputq); > + } > exit: > /* This queue should normally be empty by now */ > __skb_queue_purge(pkts); > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c > index 2bed658..27b4fd7 100644 > --- a/net/tipc/bearer.c > +++ b/net/tipc/bearer.c > @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, > struct genl_info *info) > > name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(name, "eth:lo")) { > + tipc_net(net)->loopback_trace = false; > + pr_info("Disabled packet tracing on loopback interface\n"); > + return 0; > + } > + > bearer = tipc_bearer_find(net, name); > if (!bearer) > return -EINVAL; > @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, > struct genl_info *info) > > bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(bearer, "eth:lo")) { > + tipc_net(net)->loopback_trace = true; > + pr_info("Enabled packet tracing on loopback interface\n"); > + return 0; > + } > + > if (attrs[TIPC_NLA_BEARER_DOMAIN]) > domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); > > @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct > genl_info *info) > return err; > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) > +{ > + struct net_device *dev = net->loopback_dev; > + struct sk_buff *skb, *_skb; > + int exp; > + > + skb_queue_walk(xmitq, _skb) { > + skb = pskb_copy(_skb, GFP_ATOMIC); > + if (!skb) > + continue; > + exp = SKB_DATA_ALIGN(dev->hard_header_len - > skb_headroom(skb)); > + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { > + kfree_skb(skb); > + continue; > + } > + skb_reset_network_header(skb); > + skb->dev = dev; > + skb->protocol = htons(ETH_P_TIPC); > + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, > + dev->dev_addr, skb->len); > + dev_queue_xmit(skb); > + } > +} > + > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device > *dev, > + struct packet_type *pt, struct net_device > *od) > +{ > + consume_skb(skb); > + return NET_RX_SUCCESS; > +} > + > +int tipc_attach_loopback(struct net *net) > +{ > + struct net_device *dev = net->loopback_dev; > + struct tipc_net *tn = tipc_net(net); > + > + if (!dev) > + return -ENODEV; > + dev_hold(dev); > + tn->loopback_pt.dev = dev; > + tn->loopback_pt.type = htons(ETH_P_TIPC); > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > + tn->loopback_trace = false; > + dev_add_pack(&tn->loopback_pt); > + return 0; > +} > + > +void tipc_detach_loopback(struct net *net) > +{ > + struct tipc_net *tn = tipc_net(net); > + > + dev_remove_pack(&tn->loopback_pt); > + dev_put(net->loopback_dev); > +} > + > static int __tipc_nl_add_media(struct tipc_nl_msg *msg, > struct tipc_media *media, int nlflags) > { > diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h > index 7f4c569..ef7fad9 100644 > --- a/net/tipc/bearer.h > +++ b/net/tipc/bearer.h > @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, > struct tipc_media_addr *dst); > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > struct sk_buff_head *xmitq); > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); > +int tipc_attach_loopback(struct net *net); > +void tipc_detach_loopback(struct net *net); > > /* check if device MTU is too low for tipc headers */ > 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 ed536c0..1867687 100644 > --- a/net/tipc/core.c > +++ b/net/tipc/core.c > @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) > err = tipc_bcast_init(net); > if (err) > goto out_bclink; > - > + err = tipc_attach_loopback(net); > + if (err) > + goto out_bclink; > return 0; > > out_bclink: > @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) > { > + tipc_detach_loopback(net); > tipc_net_stop(net); > tipc_bcast_stop(net); > tipc_nametbl_stop(net); > diff --git a/net/tipc/core.h b/net/tipc/core.h > index 7a68e1b..c1c2906 100644 > --- a/net/tipc/core.h > +++ b/net/tipc/core.h > @@ -67,6 +67,7 @@ struct tipc_link; > struct tipc_name_table; > struct tipc_topsrv; > struct tipc_monitor; > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); > > #define TIPC_MOD_VER "2.0.0" > > @@ -125,6 +126,10 @@ struct tipc_net { > > /* Cluster capabilities */ > u16 capabilities; > + > + /* Tracing of node internal messages */ > + struct packet_type loopback_pt; > + bool loopback_trace; > }; > > static inline struct tipc_net *tipc_net(struct net *net) > @@ -152,6 +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct > net *net) > return tipc_net(net)->topsrv; > } > > +static inline void tipc_loopback_trace(struct net *net, > + struct sk_buff_head *pkts) > +{ > + if (unlikely(tipc_net(net)->loopback_trace)) > + tipc_clone_to_loopback(net, pkts); > +} > + > static inline unsigned int tipc_hashfn(u32 addr) > { > return addr & (NODE_HTABLE_SIZE - 1); > diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c > index 99bd166..d6165ad 100644 > --- a/net/tipc/netlink.c > +++ b/net/tipc/netlink.c > @@ -261,7 +261,7 @@ struct genl_family tipc_genl_family __ro_after_init = { > .version = TIPC_GENL_V2_VERSION, > .hdrsize = 0, > .maxattr = TIPC_NLA_MAX, > - .policy = tipc_nl_policy, > + .policy = tipc_nl_policy, > .netnsok = true, > .module = THIS_MODULE, > .ops = tipc_genl_v2_ops, > diff --git a/net/tipc/node.c b/net/tipc/node.c > index 9e106d3..7e58831 100644 > --- a/net/tipc/node.c > +++ b/net/tipc/node.c > @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct > sk_buff_head *list, > int rc; > > if (in_own_node(net, dnode)) { > + tipc_loopback_trace(net, list); > tipc_sk_rcv(net, list); > return 0; > } > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c > index f345662..e3a6ba1 100644 > --- a/net/tipc/topsrv.c > +++ b/net/tipc/topsrv.c > @@ -40,6 +40,7 @@ > #include "socket.h" > #include "addr.h" > #include "msg.h" > +#include "bearer.h" > #include <net/sock.h> > #include <linux/module.h> > > @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, > struct tipc_event *evt) > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > skb_queue_head_init(&evtq); > __skb_queue_tail(&evtq, skb); > + tipc_loopback_trace(net, &evtq); > tipc_sk_rcv(net, &evtq); > } > > -- > 2.11.0 > > > > _______________________________________________ > tipc-discussion mailing list > tip...@li... > https://lists.sourceforge.net/lists/listinfo/tipc-discussion > |
From: John R. <joh...@de...> - 2019-06-19 00:11:49
|
Since node internal messages are passed directly to socket it is not possible to observe this message exchange via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is turned on/off by enabling/disabling the loopback "bearer" "eth:lo". Signed-off-by: John Rutherford <joh...@de...> --- net/tipc/bcast.c | 4 +++- net/tipc/bearer.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 3 +++ net/tipc/core.c | 5 ++++- net/tipc/core.h | 12 ++++++++++ net/tipc/node.c | 1 + net/tipc/topsrv.c | 2 ++ 7 files changed, 92 insertions(+), 2 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d 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, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + tipc_loopback_trace(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..27b4fd7 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(name, "eth:lo")) { + tipc_net(net)->loopback_trace = false; + pr_info("Disabled packet tracing on loopback interface\n"); + return 0; + } + bearer = tipc_bearer_find(net, name); if (!bearer) return -EINVAL; @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(bearer, "eth:lo")) { + tipc_net(net)->loopback_trace = true; + pr_info("Enabled packet tracing on loopback interface\n"); + return 0; + } + if (attrs[TIPC_NLA_BEARER_DOMAIN]) domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) return err; } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(xmitq, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + skb_reset_network_header(skb); + skb->dev = dev; + skb->protocol = htons(ETH_P_TIPC); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + dev_queue_xmit(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + tn->loopback_trace = false; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + static int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct tipc_media *media, int nlflags) { diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) err = tipc_bcast_init(net); if (err) goto out_bclink; - + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; return 0; out_bclink: @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..c1c2906 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -67,6 +67,7 @@ struct tipc_link; struct tipc_name_table; struct tipc_topsrv; struct tipc_monitor; +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); #define TIPC_MOD_VER "2.0.0" @@ -125,6 +126,10 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; + bool loopback_trace; }; static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) return tipc_net(net)->topsrv; } +static inline void tipc_loopback_trace(struct net *net, + struct sk_buff_head *pkts) +{ + if (unlikely(tipc_net(net)->loopback_trace)) + tipc_clone_to_loopback(net, pkts); +} + static inline unsigned int tipc_hashfn(u32 addr) { return addr & (NODE_HTABLE_SIZE - 1); diff --git a/net/tipc/node.c b/net/tipc/node.c index 9e106d3..7e58831 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, int rc; if (in_own_node(net, dnode)) { + tipc_loopback_trace(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include <net/sock.h> #include <linux/module.h> @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + tipc_loopback_trace(net, &evtq); tipc_sk_rcv(net, &evtq); } -- 2.11.0 |
From: Jon M. <jon...@er...> - 2019-06-20 12:10:48
|
Acked-by: Jon Maloy jon...@er... > -----Original Message----- > From: John Rutherford <joh...@de...> > Sent: 18-Jun-19 20:11 > To: tip...@li... > Subject: [tipc-discussion] [net-next v2] tipc: add loopback device tracking > > Since node internal messages are passed directly to socket it is not possible to > observe this message exchange via tcpdump or wireshark. > > We now remedy this by making it possible to clone such messages and send > the clones to the loopback interface. The clones are dropped at reception and > have no functional role except making the traffic visible. > > The feature is turned on/off by enabling/disabling the loopback "bearer" > "eth:lo". > > Signed-off-by: John Rutherford <joh...@de...> > --- > net/tipc/bcast.c | 4 +++- > net/tipc/bearer.c | 67 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/tipc/bearer.h | 3 +++ > net/tipc/core.c | 5 ++++- > net/tipc/core.h | 12 ++++++++++ > net/tipc/node.c | 1 + > net/tipc/topsrv.c | 2 ++ > 7 files changed, 92 insertions(+), 2 deletions(-) > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d > 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, > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > } > > - if (dests->local) > + if (dests->local) { > + tipc_loopback_trace(net, &localq); > tipc_sk_mcast_rcv(net, &localq, &inputq); > + } > exit: > /* This queue should normally be empty by now */ > __skb_queue_purge(pkts); > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..27b4fd7 > 100644 > --- a/net/tipc/bearer.c > +++ b/net/tipc/bearer.c > @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, > struct genl_info *info) > > name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(name, "eth:lo")) { > + tipc_net(net)->loopback_trace = false; > + pr_info("Disabled packet tracing on loopback interface\n"); > + return 0; > + } > + > bearer = tipc_bearer_find(net, name); > if (!bearer) > return -EINVAL; > @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, > struct genl_info *info) > > bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(bearer, "eth:lo")) { > + tipc_net(net)->loopback_trace = true; > + pr_info("Enabled packet tracing on loopback interface\n"); > + return 0; > + } > + > if (attrs[TIPC_NLA_BEARER_DOMAIN]) > domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); > > @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct > genl_info *info) > return err; > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > +*xmitq) { > + struct net_device *dev = net->loopback_dev; > + struct sk_buff *skb, *_skb; > + int exp; > + > + skb_queue_walk(xmitq, _skb) { > + skb = pskb_copy(_skb, GFP_ATOMIC); > + if (!skb) > + continue; > + exp = SKB_DATA_ALIGN(dev->hard_header_len - > skb_headroom(skb)); > + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { > + kfree_skb(skb); > + continue; > + } > + skb_reset_network_header(skb); > + skb->dev = dev; > + skb->protocol = htons(ETH_P_TIPC); > + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, > + dev->dev_addr, skb->len); > + dev_queue_xmit(skb); > + } > +} > + > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, > + struct packet_type *pt, struct net_device *od) { > + consume_skb(skb); > + return NET_RX_SUCCESS; > +} > + > +int tipc_attach_loopback(struct net *net) { > + struct net_device *dev = net->loopback_dev; > + struct tipc_net *tn = tipc_net(net); > + > + if (!dev) > + return -ENODEV; > + dev_hold(dev); > + tn->loopback_pt.dev = dev; > + tn->loopback_pt.type = htons(ETH_P_TIPC); > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > + tn->loopback_trace = false; > + dev_add_pack(&tn->loopback_pt); > + return 0; > +} > + > +void tipc_detach_loopback(struct net *net) { > + struct tipc_net *tn = tipc_net(net); > + > + dev_remove_pack(&tn->loopback_pt); > + dev_put(net->loopback_dev); > +} > + > static int __tipc_nl_add_media(struct tipc_nl_msg *msg, > struct tipc_media *media, int nlflags) { diff --git > a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 > --- a/net/tipc/bearer.h > +++ b/net/tipc/bearer.h > @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 > bearer_id, > struct tipc_media_addr *dst); > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > struct sk_buff_head *xmitq); > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > +*xmitq); int tipc_attach_loopback(struct net *net); void > +tipc_detach_loopback(struct net *net); > > /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 100644 > --- a/net/tipc/core.c > +++ b/net/tipc/core.c > @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) > err = tipc_bcast_init(net); > if (err) > goto out_bclink; > - > + err = tipc_attach_loopback(net); > + if (err) > + goto out_bclink; > return 0; > > out_bclink: > @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) { > + tipc_detach_loopback(net); > tipc_net_stop(net); > tipc_bcast_stop(net); > tipc_nametbl_stop(net); > diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..c1c2906 100644 > --- a/net/tipc/core.h > +++ b/net/tipc/core.h > @@ -67,6 +67,7 @@ struct tipc_link; > struct tipc_name_table; > struct tipc_topsrv; > struct tipc_monitor; > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > +*pkts); > > #define TIPC_MOD_VER "2.0.0" > > @@ -125,6 +126,10 @@ struct tipc_net { > > /* Cluster capabilities */ > u16 capabilities; > + > + /* Tracing of node internal messages */ > + struct packet_type loopback_pt; > + bool loopback_trace; > }; > > static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 +157,13 > @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) > return tipc_net(net)->topsrv; > } > > +static inline void tipc_loopback_trace(struct net *net, > + struct sk_buff_head *pkts) > +{ > + if (unlikely(tipc_net(net)->loopback_trace)) > + tipc_clone_to_loopback(net, pkts); > +} > + > static inline unsigned int tipc_hashfn(u32 addr) { > return addr & (NODE_HTABLE_SIZE - 1); > diff --git a/net/tipc/node.c b/net/tipc/node.c index 9e106d3..7e58831 > 100644 > --- a/net/tipc/node.c > +++ b/net/tipc/node.c > @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct > sk_buff_head *list, > int rc; > > if (in_own_node(net, dnode)) { > + tipc_loopback_trace(net, list); > tipc_sk_rcv(net, list); > return 0; > } > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 > 100644 > --- a/net/tipc/topsrv.c > +++ b/net/tipc/topsrv.c > @@ -40,6 +40,7 @@ > #include "socket.h" > #include "addr.h" > #include "msg.h" > +#include "bearer.h" > #include <net/sock.h> > #include <linux/module.h> > > @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, > struct tipc_event *evt) > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > skb_queue_head_init(&evtq); > __skb_queue_tail(&evtq, skb); > + tipc_loopback_trace(net, &evtq); > tipc_sk_rcv(net, &evtq); > } > > -- > 2.11.0 > > > > _______________________________________________ > tipc-discussion mailing list > tip...@li... > https://lists.sourceforge.net/lists/listinfo/tipc-discussion |
From: Ying X. <yin...@wi...> - 2019-06-21 12:27:08
|
Good work! Just one suggestion: it's better to add one separate kernel config to control whether the new feature is enabled or not, and its default value should be set to "Disabled" because the feature is related to debug. On 6/19/19 8:11 AM, John Rutherford wrote: > Since node internal messages are passed directly to socket it is not > possible to observe this message exchange via tcpdump or wireshark. > > We now remedy this by making it possible to clone such messages and send > the clones to the loopback interface. The clones are dropped at reception > and have no functional role except making the traffic visible. > > The feature is turned on/off by enabling/disabling the loopback "bearer" > "eth:lo". > > Signed-off-by: John Rutherford <joh...@de...> > --- > net/tipc/bcast.c | 4 +++- > net/tipc/bearer.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/tipc/bearer.h | 3 +++ > net/tipc/core.c | 5 ++++- > net/tipc/core.h | 12 ++++++++++ > net/tipc/node.c | 1 + > net/tipc/topsrv.c | 2 ++ > 7 files changed, 92 insertions(+), 2 deletions(-) > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c > index 6c997d4..235331d 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, > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > } > > - if (dests->local) > + if (dests->local) { > + tipc_loopback_trace(net, &localq); > tipc_sk_mcast_rcv(net, &localq, &inputq); > + } > exit: > /* This queue should normally be empty by now */ > __skb_queue_purge(pkts); > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c > index 2bed658..27b4fd7 100644 > --- a/net/tipc/bearer.c > +++ b/net/tipc/bearer.c > @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) > > name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(name, "eth:lo")) { > + tipc_net(net)->loopback_trace = false; > + pr_info("Disabled packet tracing on loopback interface\n"); > + return 0; > + } > + > bearer = tipc_bearer_find(net, name); > if (!bearer) > return -EINVAL; > @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) > > bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > + if (!strcmp(bearer, "eth:lo")) { > + tipc_net(net)->loopback_trace = true; > + pr_info("Enabled packet tracing on loopback interface\n"); > + return 0; > + } > + > if (attrs[TIPC_NLA_BEARER_DOMAIN]) > domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); > > @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) > return err; > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) > +{ > + struct net_device *dev = net->loopback_dev; > + struct sk_buff *skb, *_skb; > + int exp; > + > + skb_queue_walk(xmitq, _skb) { > + skb = pskb_copy(_skb, GFP_ATOMIC); > + if (!skb) > + continue; > + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); > + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { > + kfree_skb(skb); > + continue; > + } > + skb_reset_network_header(skb); > + skb->dev = dev; > + skb->protocol = htons(ETH_P_TIPC); > + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, > + dev->dev_addr, skb->len); > + dev_queue_xmit(skb); > + } > +} > + > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, > + struct packet_type *pt, struct net_device *od) > +{ > + consume_skb(skb); > + return NET_RX_SUCCESS; > +} > + > +int tipc_attach_loopback(struct net *net) > +{ > + struct net_device *dev = net->loopback_dev; > + struct tipc_net *tn = tipc_net(net); > + > + if (!dev) > + return -ENODEV; > + dev_hold(dev); > + tn->loopback_pt.dev = dev; > + tn->loopback_pt.type = htons(ETH_P_TIPC); > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > + tn->loopback_trace = false; > + dev_add_pack(&tn->loopback_pt); > + return 0; > +} > + > +void tipc_detach_loopback(struct net *net) > +{ > + struct tipc_net *tn = tipc_net(net); > + > + dev_remove_pack(&tn->loopback_pt); > + dev_put(net->loopback_dev); > +} > + > static int __tipc_nl_add_media(struct tipc_nl_msg *msg, > struct tipc_media *media, int nlflags) > { > diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h > index 7f4c569..ef7fad9 100644 > --- a/net/tipc/bearer.h > +++ b/net/tipc/bearer.h > @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, > struct tipc_media_addr *dst); > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > struct sk_buff_head *xmitq); > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); > +int tipc_attach_loopback(struct net *net); > +void tipc_detach_loopback(struct net *net); > > /* check if device MTU is too low for tipc headers */ > 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 ed536c0..1867687 100644 > --- a/net/tipc/core.c > +++ b/net/tipc/core.c > @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) > err = tipc_bcast_init(net); > if (err) > goto out_bclink; > - > + err = tipc_attach_loopback(net); > + if (err) > + goto out_bclink; > return 0; > > out_bclink: > @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) > { > + tipc_detach_loopback(net); > tipc_net_stop(net); > tipc_bcast_stop(net); > tipc_nametbl_stop(net); > diff --git a/net/tipc/core.h b/net/tipc/core.h > index 7a68e1b..c1c2906 100644 > --- a/net/tipc/core.h > +++ b/net/tipc/core.h > @@ -67,6 +67,7 @@ struct tipc_link; > struct tipc_name_table; > struct tipc_topsrv; > struct tipc_monitor; > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); > > #define TIPC_MOD_VER "2.0.0" > > @@ -125,6 +126,10 @@ struct tipc_net { > > /* Cluster capabilities */ > u16 capabilities; > + > + /* Tracing of node internal messages */ > + struct packet_type loopback_pt; > + bool loopback_trace; > }; > > static inline struct tipc_net *tipc_net(struct net *net) > @@ -152,6 +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) > return tipc_net(net)->topsrv; > } > > +static inline void tipc_loopback_trace(struct net *net, > + struct sk_buff_head *pkts) > +{ > + if (unlikely(tipc_net(net)->loopback_trace)) > + tipc_clone_to_loopback(net, pkts); > +} > + > static inline unsigned int tipc_hashfn(u32 addr) > { > return addr & (NODE_HTABLE_SIZE - 1); > diff --git a/net/tipc/node.c b/net/tipc/node.c > index 9e106d3..7e58831 100644 > --- a/net/tipc/node.c > +++ b/net/tipc/node.c > @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, > int rc; > > if (in_own_node(net, dnode)) { > + tipc_loopback_trace(net, list); > tipc_sk_rcv(net, list); > return 0; > } > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c > index f345662..e3a6ba1 100644 > --- a/net/tipc/topsrv.c > +++ b/net/tipc/topsrv.c > @@ -40,6 +40,7 @@ > #include "socket.h" > #include "addr.h" > #include "msg.h" > +#include "bearer.h" > #include <net/sock.h> > #include <linux/module.h> > > @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > skb_queue_head_init(&evtq); > __skb_queue_tail(&evtq, skb); > + tipc_loopback_trace(net, &evtq); > tipc_sk_rcv(net, &evtq); > } > > |
From: Jon M. <jon...@er...> - 2019-06-21 14:13:19
|
Hi Ying, We discussed this, and even had a first version where we did this, performing the whole attach/detach tasks in the command execution itself. This resulted in way to much new code to my taste. My greatest concern now is that some users will enable this interface because they think it is necessary (we have already seen cases of that) and then start complaining about performance. So, as a compromise, I suggested we could add a "confirmation" printout in the tipc tool when the loopback interface is enabled, to make the user understand that this is for tracing only. Do you think this would be acceptable? ///jon > -----Original Message----- > From: Ying Xue <yin...@wi...> > Sent: 21-Jun-19 08:16 > To: John Rutherford <joh...@de...>; tipc- > dis...@li... > Subject: Re: [tipc-discussion] [net-next v2] tipc: add loopback device tracking > > Good work! > > Just one suggestion: it's better to add one separate kernel config to control > whether the new feature is enabled or not, and its default value should be set > to "Disabled" because the feature is related to debug. > > On 6/19/19 8:11 AM, John Rutherford wrote: > > Since node internal messages are passed directly to socket it is not > > possible to observe this message exchange via tcpdump or wireshark. > > > > We now remedy this by making it possible to clone such messages and > > send the clones to the loopback interface. The clones are dropped at > > reception and have no functional role except making the traffic visible. > > > > The feature is turned on/off by enabling/disabling the loopback "bearer" > > "eth:lo". > > > > Signed-off-by: John Rutherford <joh...@de...> > > --- > > net/tipc/bcast.c | 4 +++- > > net/tipc/bearer.c | 67 > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > net/tipc/bearer.h | 3 +++ > > net/tipc/core.c | 5 ++++- > > net/tipc/core.h | 12 ++++++++++ > > net/tipc/node.c | 1 + > > net/tipc/topsrv.c | 2 ++ > > 7 files changed, 92 insertions(+), 2 deletions(-) > > > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index > > 6c997d4..235331d 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, > > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > > } > > > > - if (dests->local) > > + if (dests->local) { > > + tipc_loopback_trace(net, &localq); > > tipc_sk_mcast_rcv(net, &localq, &inputq); > > + } > > exit: > > /* This queue should normally be empty by now */ > > __skb_queue_purge(pkts); > > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index > > 2bed658..27b4fd7 100644 > > --- a/net/tipc/bearer.c > > +++ b/net/tipc/bearer.c > > @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, > > struct genl_info *info) > > > > name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > > > + if (!strcmp(name, "eth:lo")) { > > + tipc_net(net)->loopback_trace = false; > > + pr_info("Disabled packet tracing on loopback interface\n"); > > + return 0; > > + } > > + > > bearer = tipc_bearer_find(net, name); > > if (!bearer) > > return -EINVAL; > > @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, > > struct genl_info *info) > > > > bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); > > > > + if (!strcmp(bearer, "eth:lo")) { > > + tipc_net(net)->loopback_trace = true; > > + pr_info("Enabled packet tracing on loopback interface\n"); > > + return 0; > > + } > > + > > if (attrs[TIPC_NLA_BEARER_DOMAIN]) > > domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); > > > > @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, > struct genl_info *info) > > return err; > > } > > > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > > +*xmitq) { > > + struct net_device *dev = net->loopback_dev; > > + struct sk_buff *skb, *_skb; > > + int exp; > > + > > + skb_queue_walk(xmitq, _skb) { > > + skb = pskb_copy(_skb, GFP_ATOMIC); > > + if (!skb) > > + continue; > > + exp = SKB_DATA_ALIGN(dev->hard_header_len - > skb_headroom(skb)); > > + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { > > + kfree_skb(skb); > > + continue; > > + } > > + skb_reset_network_header(skb); > > + skb->dev = dev; > > + skb->protocol = htons(ETH_P_TIPC); > > + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, > > + dev->dev_addr, skb->len); > > + dev_queue_xmit(skb); > > + } > > +} > > + > > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device > *dev, > > + struct packet_type *pt, struct net_device *od) { > > + consume_skb(skb); > > + return NET_RX_SUCCESS; > > +} > > + > > +int tipc_attach_loopback(struct net *net) { > > + struct net_device *dev = net->loopback_dev; > > + struct tipc_net *tn = tipc_net(net); > > + > > + if (!dev) > > + return -ENODEV; > > + dev_hold(dev); > > + tn->loopback_pt.dev = dev; > > + tn->loopback_pt.type = htons(ETH_P_TIPC); > > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > > + tn->loopback_trace = false; > > + dev_add_pack(&tn->loopback_pt); > > + return 0; > > +} > > + > > +void tipc_detach_loopback(struct net *net) { > > + struct tipc_net *tn = tipc_net(net); > > + > > + dev_remove_pack(&tn->loopback_pt); > > + dev_put(net->loopback_dev); > > +} > > + > > static int __tipc_nl_add_media(struct tipc_nl_msg *msg, > > struct tipc_media *media, int nlflags) { diff --git > > a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 > > --- a/net/tipc/bearer.h > > +++ b/net/tipc/bearer.h > > @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 > bearer_id, > > struct tipc_media_addr *dst); void > > tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > > struct sk_buff_head *xmitq); > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > > +*xmitq); int tipc_attach_loopback(struct net *net); void > > +tipc_detach_loopback(struct net *net); > > > > /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 > > 100644 > > --- a/net/tipc/core.c > > +++ b/net/tipc/core.c > > @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) > > err = tipc_bcast_init(net); > > if (err) > > goto out_bclink; > > - > > + err = tipc_attach_loopback(net); > > + if (err) > > + goto out_bclink; > > return 0; > > > > out_bclink: > > @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) > > > > static void __net_exit tipc_exit_net(struct net *net) { > > + tipc_detach_loopback(net); > > tipc_net_stop(net); > > tipc_bcast_stop(net); > > tipc_nametbl_stop(net); > > diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..c1c2906 > > 100644 > > --- a/net/tipc/core.h > > +++ b/net/tipc/core.h > > @@ -67,6 +67,7 @@ struct tipc_link; > > struct tipc_name_table; > > struct tipc_topsrv; > > struct tipc_monitor; > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > > +*pkts); > > > > #define TIPC_MOD_VER "2.0.0" > > > > @@ -125,6 +126,10 @@ struct tipc_net { > > > > /* Cluster capabilities */ > > u16 capabilities; > > + > > + /* Tracing of node internal messages */ > > + struct packet_type loopback_pt; > > + bool loopback_trace; > > }; > > > > static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 > > +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) > > return tipc_net(net)->topsrv; > > } > > > > +static inline void tipc_loopback_trace(struct net *net, > > + struct sk_buff_head *pkts) { > > + if (unlikely(tipc_net(net)->loopback_trace)) > > + tipc_clone_to_loopback(net, pkts); > > +} > > + > > static inline unsigned int tipc_hashfn(u32 addr) { > > return addr & (NODE_HTABLE_SIZE - 1); diff --git a/net/tipc/node.c > > b/net/tipc/node.c index 9e106d3..7e58831 100644 > > --- a/net/tipc/node.c > > +++ b/net/tipc/node.c > > @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct > sk_buff_head *list, > > int rc; > > > > if (in_own_node(net, dnode)) { > > + tipc_loopback_trace(net, list); > > tipc_sk_rcv(net, list); > > return 0; > > } > > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index > > f345662..e3a6ba1 100644 > > --- a/net/tipc/topsrv.c > > +++ b/net/tipc/topsrv.c > > @@ -40,6 +40,7 @@ > > #include "socket.h" > > #include "addr.h" > > #include "msg.h" > > +#include "bearer.h" > > #include <net/sock.h> > > #include <linux/module.h> > > > > @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, > struct tipc_event *evt) > > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > > skb_queue_head_init(&evtq); > > __skb_queue_tail(&evtq, skb); > > + tipc_loopback_trace(net, &evtq); > > tipc_sk_rcv(net, &evtq); > > } > > > > > > > _______________________________________________ > tipc-discussion mailing list > tip...@li... > https://lists.sourceforge.net/lists/listinfo/tipc-discussion |
From: Ying X. <yin...@wi...> - 2019-06-24 02:41:27
|
On 6/21/19 9:41 PM, Jon Maloy wrote: > Hi Ying, > We discussed this, and even had a first version where we did this, performing the whole attach/detach tasks in the command execution itself. This resulted in way to much new code to my taste. > My greatest concern now is that some users will enable this interface because they think it is necessary (we have already seen cases of that) and then start complaining about performance. > So, as a compromise, I suggested we could add a "confirmation" printout in the tipc tool when the loopback interface is enabled, to make the user understand that this is for tracing only. > Do you think this would be acceptable? Make sense to me. Thanks, Ying > > ///jon > > >> -----Original Message----- >> From: Ying Xue <yin...@wi...> >> Sent: 21-Jun-19 08:16 >> To: John Rutherford <joh...@de...>; tipc- >> dis...@li... >> Subject: Re: [tipc-discussion] [net-next v2] tipc: add loopback device tracking >> >> Good work! >> >> Just one suggestion: it's better to add one separate kernel config to control >> whether the new feature is enabled or not, and its default value should be set >> to "Disabled" because the feature is related to debug. >> >> On 6/19/19 8:11 AM, John Rutherford wrote: >>> Since node internal messages are passed directly to socket it is not >>> possible to observe this message exchange via tcpdump or wireshark. >>> >>> We now remedy this by making it possible to clone such messages and >>> send the clones to the loopback interface. The clones are dropped at >>> reception and have no functional role except making the traffic visible. >>> >>> The feature is turned on/off by enabling/disabling the loopback "bearer" >>> "eth:lo". >>> >>> Signed-off-by: John Rutherford <joh...@de...> >>> --- >>> net/tipc/bcast.c | 4 +++- >>> net/tipc/bearer.c | 67 >>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ >>> net/tipc/bearer.h | 3 +++ >>> net/tipc/core.c | 5 ++++- >>> net/tipc/core.h | 12 ++++++++++ >>> net/tipc/node.c | 1 + >>> net/tipc/topsrv.c | 2 ++ >>> 7 files changed, 92 insertions(+), 2 deletions(-) >>> >>> diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index >>> 6c997d4..235331d 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, >>> rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); >>> } >>> >>> - if (dests->local) >>> + if (dests->local) { >>> + tipc_loopback_trace(net, &localq); >>> tipc_sk_mcast_rcv(net, &localq, &inputq); >>> + } >>> exit: >>> /* This queue should normally be empty by now */ >>> __skb_queue_purge(pkts); >>> diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index >>> 2bed658..27b4fd7 100644 >>> --- a/net/tipc/bearer.c >>> +++ b/net/tipc/bearer.c >>> @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, >>> struct genl_info *info) >>> >>> name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); >>> >>> + if (!strcmp(name, "eth:lo")) { >>> + tipc_net(net)->loopback_trace = false; >>> + pr_info("Disabled packet tracing on loopback interface\n"); >>> + return 0; >>> + } >>> + >>> bearer = tipc_bearer_find(net, name); >>> if (!bearer) >>> return -EINVAL; >>> @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, >>> struct genl_info *info) >>> >>> bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); >>> >>> + if (!strcmp(bearer, "eth:lo")) { >>> + tipc_net(net)->loopback_trace = true; >>> + pr_info("Enabled packet tracing on loopback interface\n"); >>> + return 0; >>> + } >>> + >>> if (attrs[TIPC_NLA_BEARER_DOMAIN]) >>> domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); >>> >>> @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, >> struct genl_info *info) >>> return err; >>> } >>> >>> +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head >>> +*xmitq) { >>> + struct net_device *dev = net->loopback_dev; >>> + struct sk_buff *skb, *_skb; >>> + int exp; >>> + >>> + skb_queue_walk(xmitq, _skb) { >>> + skb = pskb_copy(_skb, GFP_ATOMIC); >>> + if (!skb) >>> + continue; >>> + exp = SKB_DATA_ALIGN(dev->hard_header_len - >> skb_headroom(skb)); >>> + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { >>> + kfree_skb(skb); >>> + continue; >>> + } >>> + skb_reset_network_header(skb); >>> + skb->dev = dev; >>> + skb->protocol = htons(ETH_P_TIPC); >>> + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, >>> + dev->dev_addr, skb->len); >>> + dev_queue_xmit(skb); >>> + } >>> +} >>> + >>> +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device >> *dev, >>> + struct packet_type *pt, struct net_device *od) { >>> + consume_skb(skb); >>> + return NET_RX_SUCCESS; >>> +} >>> + >>> +int tipc_attach_loopback(struct net *net) { >>> + struct net_device *dev = net->loopback_dev; >>> + struct tipc_net *tn = tipc_net(net); >>> + >>> + if (!dev) >>> + return -ENODEV; >>> + dev_hold(dev); >>> + tn->loopback_pt.dev = dev; >>> + tn->loopback_pt.type = htons(ETH_P_TIPC); >>> + tn->loopback_pt.func = tipc_loopback_rcv_pkt; >>> + tn->loopback_trace = false; >>> + dev_add_pack(&tn->loopback_pt); >>> + return 0; >>> +} >>> + >>> +void tipc_detach_loopback(struct net *net) { >>> + struct tipc_net *tn = tipc_net(net); >>> + >>> + dev_remove_pack(&tn->loopback_pt); >>> + dev_put(net->loopback_dev); >>> +} >>> + >>> static int __tipc_nl_add_media(struct tipc_nl_msg *msg, >>> struct tipc_media *media, int nlflags) { diff --git >>> a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 >>> --- a/net/tipc/bearer.h >>> +++ b/net/tipc/bearer.h >>> @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 >> bearer_id, >>> struct tipc_media_addr *dst); void >>> tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, >>> struct sk_buff_head *xmitq); >>> +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head >>> +*xmitq); int tipc_attach_loopback(struct net *net); void >>> +tipc_detach_loopback(struct net *net); >>> >>> /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 >>> 100644 >>> --- a/net/tipc/core.c >>> +++ b/net/tipc/core.c >>> @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) >>> err = tipc_bcast_init(net); >>> if (err) >>> goto out_bclink; >>> - >>> + err = tipc_attach_loopback(net); >>> + if (err) >>> + goto out_bclink; >>> return 0; >>> >>> out_bclink: >>> @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) >>> >>> static void __net_exit tipc_exit_net(struct net *net) { >>> + tipc_detach_loopback(net); >>> tipc_net_stop(net); >>> tipc_bcast_stop(net); >>> tipc_nametbl_stop(net); >>> diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..c1c2906 >>> 100644 >>> --- a/net/tipc/core.h >>> +++ b/net/tipc/core.h >>> @@ -67,6 +67,7 @@ struct tipc_link; >>> struct tipc_name_table; >>> struct tipc_topsrv; >>> struct tipc_monitor; >>> +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head >>> +*pkts); >>> >>> #define TIPC_MOD_VER "2.0.0" >>> >>> @@ -125,6 +126,10 @@ struct tipc_net { >>> >>> /* Cluster capabilities */ >>> u16 capabilities; >>> + >>> + /* Tracing of node internal messages */ >>> + struct packet_type loopback_pt; >>> + bool loopback_trace; >>> }; >>> >>> static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 >>> +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) >>> return tipc_net(net)->topsrv; >>> } >>> >>> +static inline void tipc_loopback_trace(struct net *net, >>> + struct sk_buff_head *pkts) { >>> + if (unlikely(tipc_net(net)->loopback_trace)) >>> + tipc_clone_to_loopback(net, pkts); >>> +} >>> + >>> static inline unsigned int tipc_hashfn(u32 addr) { >>> return addr & (NODE_HTABLE_SIZE - 1); diff --git a/net/tipc/node.c >>> b/net/tipc/node.c index 9e106d3..7e58831 100644 >>> --- a/net/tipc/node.c >>> +++ b/net/tipc/node.c >>> @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct >> sk_buff_head *list, >>> int rc; >>> >>> if (in_own_node(net, dnode)) { >>> + tipc_loopback_trace(net, list); >>> tipc_sk_rcv(net, list); >>> return 0; >>> } >>> diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index >>> f345662..e3a6ba1 100644 >>> --- a/net/tipc/topsrv.c >>> +++ b/net/tipc/topsrv.c >>> @@ -40,6 +40,7 @@ >>> #include "socket.h" >>> #include "addr.h" >>> #include "msg.h" >>> +#include "bearer.h" >>> #include <net/sock.h> >>> #include <linux/module.h> >>> >>> @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, >> struct tipc_event *evt) >>> memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); >>> skb_queue_head_init(&evtq); >>> __skb_queue_tail(&evtq, skb); >>> + tipc_loopback_trace(net, &evtq); >>> tipc_sk_rcv(net, &evtq); >>> } >>> >>> >> >> >> _______________________________________________ >> tipc-discussion mailing list >> tip...@li... >> https://lists.sourceforge.net/lists/listinfo/tipc-discussion > |
From: John R. <joh...@de...> - 2019-06-24 04:00:55
|
Since node internal messages are passed directly to socket it is not possible to observe this message exchange via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is turned on/off by enabling/disabling the loopback "bearer" "eth:lo". Acked-by: Jon Maloy <jon...@er...> Signed-off-by: John Rutherford <joh...@de...> --- net/tipc/bcast.c | 4 +++- net/tipc/bearer.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 3 +++ net/tipc/core.c | 5 ++++- net/tipc/core.h | 12 ++++++++++ net/tipc/node.c | 1 + net/tipc/topsrv.c | 2 ++ 7 files changed, 92 insertions(+), 2 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d 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, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + tipc_loopback_trace(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..27b4fd7 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -836,6 +836,12 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(name, "eth:lo")) { + tipc_net(net)->loopback_trace = false; + pr_info("Disabled packet tracing on loopback interface\n"); + return 0; + } + bearer = tipc_bearer_find(net, name); if (!bearer) return -EINVAL; @@ -881,6 +887,12 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) bearer = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + if (!strcmp(bearer, "eth:lo")) { + tipc_net(net)->loopback_trace = true; + pr_info("Enabled packet tracing on loopback interface\n"); + return 0; + } + if (attrs[TIPC_NLA_BEARER_DOMAIN]) domain = nla_get_u32(attrs[TIPC_NLA_BEARER_DOMAIN]); @@ -1021,6 +1033,61 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) return err; } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(xmitq, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + skb_reset_network_header(skb); + skb->dev = dev; + skb->protocol = htons(ETH_P_TIPC); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + dev_queue_xmit(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + tn->loopback_trace = false; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + static int __tipc_nl_add_media(struct tipc_nl_msg *msg, struct tipc_media *media, int nlflags) { diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ef7fad9 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -232,6 +232,9 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *xmitq); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); /* check if device MTU is too low for tipc headers */ 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 ed536c0..1867687 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -81,7 +81,9 @@ static int __net_init tipc_init_net(struct net *net) err = tipc_bcast_init(net); if (err) goto out_bclink; - + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; return 0; out_bclink: @@ -94,6 +96,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..c1c2906 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -67,6 +67,7 @@ struct tipc_link; struct tipc_name_table; struct tipc_topsrv; struct tipc_monitor; +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); #define TIPC_MOD_VER "2.0.0" @@ -125,6 +126,10 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; + bool loopback_trace; }; static inline struct tipc_net *tipc_net(struct net *net) @@ -152,6 +157,13 @@ static inline struct tipc_topsrv *tipc_topsrv(struct net *net) return tipc_net(net)->topsrv; } +static inline void tipc_loopback_trace(struct net *net, + struct sk_buff_head *pkts) +{ + if (unlikely(tipc_net(net)->loopback_trace)) + tipc_clone_to_loopback(net, pkts); +} + static inline unsigned int tipc_hashfn(u32 addr) { return addr & (NODE_HTABLE_SIZE - 1); diff --git a/net/tipc/node.c b/net/tipc/node.c index 9e106d3..7e58831 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1439,6 +1439,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, int rc; if (in_own_node(net, dnode)) { + tipc_loopback_trace(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include <net/sock.h> #include <linux/module.h> @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + tipc_loopback_trace(net, &evtq); tipc_sk_rcv(net, &evtq); } -- 2.11.0 |
From: <joh...@de...> - 2019-07-19 03:10:39
|
From: John Rutherford <joh...@de...> Since node internal messages are passed directly to the socket, it is not possible to observe those messages via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is enabled if network taps are active for the loopback device. pcap filtering restrictions require the messages to be presented to the receiving side of the loopback device. v3 - Function dev_nit_active used to check for network taps. - Procedure netif_rx_ni used to send cloned messages to loopback device. Signed-off-by: John Rutherford <joh...@de...> --- net/tipc/bcast.c | 4 +++- net/tipc/bearer.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 10 +++++++++ net/tipc/core.c | 5 +++++ net/tipc/core.h | 3 +++ net/tipc/node.c | 1 + net/tipc/topsrv.c | 2 ++ 7 files changed, 89 insertions(+), 1 deletion(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d 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, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + tipc_loopback_trace(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..5273ec5 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -389,6 +389,12 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, dev_put(dev); return -EINVAL; } + if (dev == net->loopback_dev) { + dev_put(dev); + pr_info("Bearer <%s>: loopback device not permitted\n", + b->name); + return -EINVAL; + } /* Autoconfigure own node identity if needed */ if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { @@ -674,6 +680,65 @@ void tipc_bearer_stop(struct net *net) } } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(pkts, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + + skb_reset_network_header(skb); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->protocol = eth_type_trans(skb, dev); + netif_rx_ni(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + /* Caller should hold rtnl_lock to protect the bearer */ static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct tipc_bearer *bearer, int nlflags) diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ea0f3c4 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, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); + +static inline void tipc_loopback_trace(struct net *net, + struct sk_buff_head *pkts) +{ + if (unlikely(dev_nit_active(net->loopback_dev))) + tipc_clone_to_loopback(net, pkts); +} /* check if device MTU is too low for tipc headers */ 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 c837072..23cb379 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) if (err) goto out_bclink; + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; + return 0; out_bclink: @@ -94,6 +98,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..60d8295 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -125,6 +125,9 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; }; static inline struct tipc_net *tipc_net(struct net *net) diff --git a/net/tipc/node.c b/net/tipc/node.c index 550581d..16d251b 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, int rc; if (in_own_node(net, dnode)) { + tipc_loopback_trace(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include <net/sock.h> #include <linux/module.h> @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + tipc_loopback_trace(net, &evtq); tipc_sk_rcv(net, &evtq); } -- 2.11.0 |
From: Jon M. <jon...@er...> - 2019-07-30 12:51:05
|
Acked-by: Jon Maloy <jon...@er...> I just have one minor comment. See below. And forget about what I said about "on the fly" device detection. Since we have to register a handler anyway that wouldn't improve anything. ///jon > -----Original Message----- > From: joh...@de... <joh...@de...> > Sent: 18-Jul-19 23:10 > To: tip...@li... > Subject: [tipc-discussion] [net-next v3] tipc: add loopback device tracking > > From: John Rutherford <joh...@de...> > > Since node internal messages are passed directly to the socket, it is not > possible to observe those messages via tcpdump or wireshark. > > We now remedy this by making it possible to clone such messages and send > the clones to the loopback interface. The clones are dropped at reception and > have no functional role except making the traffic visible. > > The feature is enabled if network taps are active for the loopback device. > pcap filtering restrictions require the messages to be presented to the > receiving side of the loopback device. > > v3 - Function dev_nit_active used to check for network taps. > - Procedure netif_rx_ni used to send cloned messages to loopback device. > > Signed-off-by: John Rutherford <joh...@de...> > --- > net/tipc/bcast.c | 4 +++- > net/tipc/bearer.c | 65 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/tipc/bearer.h | 10 +++++++++ > net/tipc/core.c | 5 +++++ > net/tipc/core.h | 3 +++ > net/tipc/node.c | 1 + > net/tipc/topsrv.c | 2 ++ > 7 files changed, 89 insertions(+), 1 deletion(-) > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d > 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, > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > } > > - if (dests->local) > + if (dests->local) { > + tipc_loopback_trace(net, &localq); > tipc_sk_mcast_rcv(net, &localq, &inputq); > + } > exit: > /* This queue should normally be empty by now */ > __skb_queue_purge(pkts); > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..5273ec5 > 100644 > --- a/net/tipc/bearer.c > +++ b/net/tipc/bearer.c > @@ -389,6 +389,12 @@ int tipc_enable_l2_media(struct net *net, struct > tipc_bearer *b, > dev_put(dev); > return -EINVAL; > } > + if (dev == net->loopback_dev) { > + dev_put(dev); > + pr_info("Bearer <%s>: loopback device not permitted\n", Or maybe: "Enabling <%s> not permitted\n", b->name); > + return -EINVAL; > + } > > /* Autoconfigure own node identity if needed */ > if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { @@ -674,6 > +680,65 @@ void tipc_bearer_stop(struct net *net) > } > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts) > +{ > + struct net_device *dev = net->loopback_dev; > + struct sk_buff *skb, *_skb; > + int exp; > + > + skb_queue_walk(pkts, _skb) { > + skb = pskb_copy(_skb, GFP_ATOMIC); > + if (!skb) > + continue; > + > + exp = SKB_DATA_ALIGN(dev->hard_header_len - > skb_headroom(skb)); > + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { > + kfree_skb(skb); > + continue; > + } > + > + skb_reset_network_header(skb); > + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, > + dev->dev_addr, skb->len); > + skb->dev = dev; > + skb->pkt_type = PACKET_HOST; > + skb->ip_summed = CHECKSUM_UNNECESSARY; > + skb->protocol = eth_type_trans(skb, dev); > + netif_rx_ni(skb); > + } > +} > + > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, > + struct packet_type *pt, struct net_device *od) { > + consume_skb(skb); > + return NET_RX_SUCCESS; > +} > + > +int tipc_attach_loopback(struct net *net) { > + struct net_device *dev = net->loopback_dev; > + struct tipc_net *tn = tipc_net(net); > + > + if (!dev) > + return -ENODEV; > + > + dev_hold(dev); > + tn->loopback_pt.dev = dev; > + tn->loopback_pt.type = htons(ETH_P_TIPC); > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > + dev_add_pack(&tn->loopback_pt); > + return 0; > +} > + > +void tipc_detach_loopback(struct net *net) { > + struct tipc_net *tn = tipc_net(net); > + > + dev_remove_pack(&tn->loopback_pt); > + dev_put(net->loopback_dev); > +} > + > /* Caller should hold rtnl_lock to protect the bearer */ static int > __tipc_nl_add_bearer(struct tipc_nl_msg *msg, > struct tipc_bearer *bearer, int nlflags) diff --git > a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ea0f3c4 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, > struct tipc_media_addr *dst); > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > struct sk_buff_head *xmitq); > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head > +*pkts); int tipc_attach_loopback(struct net *net); void > +tipc_detach_loopback(struct net *net); > + > +static inline void tipc_loopback_trace(struct net *net, > + struct sk_buff_head *pkts) > +{ > + if (unlikely(dev_nit_active(net->loopback_dev))) > + tipc_clone_to_loopback(net, pkts); > +} > > /* check if device MTU is too low for tipc headers */ 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 c837072..23cb379 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) > if (err) > goto out_bclink; > > + err = tipc_attach_loopback(net); > + if (err) > + goto out_bclink; > + > return 0; > > out_bclink: > @@ -94,6 +98,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) { > + tipc_detach_loopback(net); > tipc_net_stop(net); > tipc_bcast_stop(net); > tipc_nametbl_stop(net); > diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..60d8295 100644 > --- a/net/tipc/core.h > +++ b/net/tipc/core.h > @@ -125,6 +125,9 @@ struct tipc_net { > > /* Cluster capabilities */ > u16 capabilities; > + > + /* Tracing of node internal messages */ > + struct packet_type loopback_pt; > }; > > static inline struct tipc_net *tipc_net(struct net *net) diff --git > a/net/tipc/node.c b/net/tipc/node.c index 550581d..16d251b 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, > int rc; > > if (in_own_node(net, dnode)) { > + tipc_loopback_trace(net, list); > tipc_sk_rcv(net, list); > return 0; > } > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 > 100644 > --- a/net/tipc/topsrv.c > +++ b/net/tipc/topsrv.c > @@ -40,6 +40,7 @@ > #include "socket.h" > #include "addr.h" > #include "msg.h" > +#include "bearer.h" > #include <net/sock.h> > #include <linux/module.h> > > @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, > struct tipc_event *evt) > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > skb_queue_head_init(&evtq); > __skb_queue_tail(&evtq, skb); > + tipc_loopback_trace(net, &evtq); > tipc_sk_rcv(net, &evtq); > } > > -- > 2.11.0 > > > > _______________________________________________ > tipc-discussion mailing list > tip...@li... > https://lists.sourceforge.net/lists/listinfo/tipc-discussion |
From: Ying X. <yin...@wi...> - 2019-07-31 13:35:19
|
On 7/19/19 11:10 AM, joh...@de... wrote: > From: John Rutherford <joh...@de...> > > Since node internal messages are passed directly to the socket, it is not > possible to observe those messages via tcpdump or wireshark. > > We now remedy this by making it possible to clone such messages and send > the clones to the loopback interface. The clones are dropped at reception > and have no functional role except making the traffic visible. > > The feature is enabled if network taps are active for the loopback device. > pcap filtering restrictions require the messages to be presented to the > receiving side of the loopback device. > > v3 - Function dev_nit_active used to check for network taps. > - Procedure netif_rx_ni used to send cloned messages to loopback device. > > Signed-off-by: John Rutherford <joh...@de...> Acked-by: Ying Xue <yin...@wi...> > --- > net/tipc/bcast.c | 4 +++- > net/tipc/bearer.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > net/tipc/bearer.h | 10 +++++++++ > net/tipc/core.c | 5 +++++ > net/tipc/core.h | 3 +++ > net/tipc/node.c | 1 + > net/tipc/topsrv.c | 2 ++ > 7 files changed, 89 insertions(+), 1 deletion(-) > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c > index 6c997d4..235331d 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, > rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); > } > > - if (dests->local) > + if (dests->local) { > + tipc_loopback_trace(net, &localq); > tipc_sk_mcast_rcv(net, &localq, &inputq); > + } > exit: > /* This queue should normally be empty by now */ > __skb_queue_purge(pkts); > diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c > index 2bed658..5273ec5 100644 > --- a/net/tipc/bearer.c > +++ b/net/tipc/bearer.c > @@ -389,6 +389,12 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b, > dev_put(dev); > return -EINVAL; > } > + if (dev == net->loopback_dev) { > + dev_put(dev); > + pr_info("Bearer <%s>: loopback device not permitted\n", > + b->name); > + return -EINVAL; > + } > > /* Autoconfigure own node identity if needed */ > if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { > @@ -674,6 +680,65 @@ void tipc_bearer_stop(struct net *net) > } > } > > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts) > +{ > + struct net_device *dev = net->loopback_dev; > + struct sk_buff *skb, *_skb; > + int exp; > + > + skb_queue_walk(pkts, _skb) { > + skb = pskb_copy(_skb, GFP_ATOMIC); > + if (!skb) > + continue; > + > + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); > + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { > + kfree_skb(skb); > + continue; > + } > + > + skb_reset_network_header(skb); > + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, > + dev->dev_addr, skb->len); > + skb->dev = dev; > + skb->pkt_type = PACKET_HOST; > + skb->ip_summed = CHECKSUM_UNNECESSARY; > + skb->protocol = eth_type_trans(skb, dev); > + netif_rx_ni(skb); > + } > +} > + > +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, > + struct packet_type *pt, struct net_device *od) > +{ > + consume_skb(skb); > + return NET_RX_SUCCESS; > +} > + > +int tipc_attach_loopback(struct net *net) > +{ > + struct net_device *dev = net->loopback_dev; > + struct tipc_net *tn = tipc_net(net); > + > + if (!dev) > + return -ENODEV; > + > + dev_hold(dev); > + tn->loopback_pt.dev = dev; > + tn->loopback_pt.type = htons(ETH_P_TIPC); > + tn->loopback_pt.func = tipc_loopback_rcv_pkt; > + dev_add_pack(&tn->loopback_pt); > + return 0; > +} > + > +void tipc_detach_loopback(struct net *net) > +{ > + struct tipc_net *tn = tipc_net(net); > + > + dev_remove_pack(&tn->loopback_pt); > + dev_put(net->loopback_dev); > +} > + > /* Caller should hold rtnl_lock to protect the bearer */ > static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, > struct tipc_bearer *bearer, int nlflags) > diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h > index 7f4c569..ea0f3c4 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, > struct tipc_media_addr *dst); > void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, > struct sk_buff_head *xmitq); > +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); > +int tipc_attach_loopback(struct net *net); > +void tipc_detach_loopback(struct net *net); > + > +static inline void tipc_loopback_trace(struct net *net, > + struct sk_buff_head *pkts) > +{ > + if (unlikely(dev_nit_active(net->loopback_dev))) > + tipc_clone_to_loopback(net, pkts); > +} > > /* check if device MTU is too low for tipc headers */ > 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 c837072..23cb379 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) > if (err) > goto out_bclink; > > + err = tipc_attach_loopback(net); > + if (err) > + goto out_bclink; > + > return 0; > > out_bclink: > @@ -94,6 +98,7 @@ static int __net_init tipc_init_net(struct net *net) > > static void __net_exit tipc_exit_net(struct net *net) > { > + tipc_detach_loopback(net); > tipc_net_stop(net); > tipc_bcast_stop(net); > tipc_nametbl_stop(net); > diff --git a/net/tipc/core.h b/net/tipc/core.h > index 7a68e1b..60d8295 100644 > --- a/net/tipc/core.h > +++ b/net/tipc/core.h > @@ -125,6 +125,9 @@ struct tipc_net { > > /* Cluster capabilities */ > u16 capabilities; > + > + /* Tracing of node internal messages */ > + struct packet_type loopback_pt; > }; > > static inline struct tipc_net *tipc_net(struct net *net) > diff --git a/net/tipc/node.c b/net/tipc/node.c > index 550581d..16d251b 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, > int rc; > > if (in_own_node(net, dnode)) { > + tipc_loopback_trace(net, list); > tipc_sk_rcv(net, list); > return 0; > } > diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c > index f345662..e3a6ba1 100644 > --- a/net/tipc/topsrv.c > +++ b/net/tipc/topsrv.c > @@ -40,6 +40,7 @@ > #include "socket.h" > #include "addr.h" > #include "msg.h" > +#include "bearer.h" > #include <net/sock.h> > #include <linux/module.h> > > @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) > memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); > skb_queue_head_init(&evtq); > __skb_queue_tail(&evtq, skb); > + tipc_loopback_trace(net, &evtq); > tipc_sk_rcv(net, &evtq); > } > > |
From: <joh...@de...> - 2019-08-07 02:53:08
|
From: John Rutherford <joh...@de...> Since node internal messages are passed directly to the socket, it is not possible to observe those messages via tcpdump or wireshark. We now remedy this by making it possible to clone such messages and send the clones to the loopback interface. The clones are dropped at reception and have no functional role except making the traffic visible. The feature is enabled if network taps are active for the loopback device. pcap filtering restrictions require the messages to be presented to the receiving side of the loopback device. v3 - Function dev_nit_active used to check for network taps. - Procedure netif_rx_ni used to send cloned messages to loopback device. Signed-off-by: John Rutherford <joh...@de...> Acked-by: Jon Maloy <jon...@er...> Acked-by: Ying Xue <yin...@wi...> --- net/tipc/bcast.c | 4 +++- net/tipc/bearer.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/bearer.h | 10 +++++++++ net/tipc/core.c | 5 +++++ net/tipc/core.h | 3 +++ net/tipc/node.c | 1 + net/tipc/topsrv.c | 2 ++ 7 files changed, 88 insertions(+), 1 deletion(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 6c997d4..235331d 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, rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); } - if (dests->local) + if (dests->local) { + tipc_loopback_trace(net, &localq); tipc_sk_mcast_rcv(net, &localq, &inputq); + } exit: /* This queue should normally be empty by now */ __skb_queue_purge(pkts); diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2bed658..93c9616 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, dev_put(dev); return -EINVAL; } + if (dev == net->loopback_dev) { + dev_put(dev); + pr_info("Enabling <%s> not permitted\n", b->name); + return -EINVAL; + } /* Autoconfigure own node identity if needed */ if (!tipc_own_id(net) && hwaddr_len <= NODE_ID_LEN) { @@ -674,6 +679,65 @@ void tipc_bearer_stop(struct net *net) } } +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts) +{ + struct net_device *dev = net->loopback_dev; + struct sk_buff *skb, *_skb; + int exp; + + skb_queue_walk(pkts, _skb) { + skb = pskb_copy(_skb, GFP_ATOMIC); + if (!skb) + continue; + + exp = SKB_DATA_ALIGN(dev->hard_header_len - skb_headroom(skb)); + if (exp > 0 && pskb_expand_head(skb, exp, 0, GFP_ATOMIC)) { + kfree_skb(skb); + continue; + } + + skb_reset_network_header(skb); + dev_hard_header(skb, dev, ETH_P_TIPC, dev->dev_addr, + dev->dev_addr, skb->len); + skb->dev = dev; + skb->pkt_type = PACKET_HOST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->protocol = eth_type_trans(skb, dev); + netif_rx_ni(skb); + } +} + +static int tipc_loopback_rcv_pkt(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *od) +{ + consume_skb(skb); + return NET_RX_SUCCESS; +} + +int tipc_attach_loopback(struct net *net) +{ + struct net_device *dev = net->loopback_dev; + struct tipc_net *tn = tipc_net(net); + + if (!dev) + return -ENODEV; + + dev_hold(dev); + tn->loopback_pt.dev = dev; + tn->loopback_pt.type = htons(ETH_P_TIPC); + tn->loopback_pt.func = tipc_loopback_rcv_pkt; + dev_add_pack(&tn->loopback_pt); + return 0; +} + +void tipc_detach_loopback(struct net *net) +{ + struct tipc_net *tn = tipc_net(net); + + dev_remove_pack(&tn->loopback_pt); + dev_put(net->loopback_dev); +} + /* Caller should hold rtnl_lock to protect the bearer */ static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg, struct tipc_bearer *bearer, int nlflags) diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 7f4c569..ea0f3c4 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, struct tipc_media_addr *dst); void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id, struct sk_buff_head *xmitq); +void tipc_clone_to_loopback(struct net *net, struct sk_buff_head *pkts); +int tipc_attach_loopback(struct net *net); +void tipc_detach_loopback(struct net *net); + +static inline void tipc_loopback_trace(struct net *net, + struct sk_buff_head *pkts) +{ + if (unlikely(dev_nit_active(net->loopback_dev))) + tipc_clone_to_loopback(net, pkts); +} /* check if device MTU is too low for tipc headers */ 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 c837072..23cb379 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) if (err) goto out_bclink; + err = tipc_attach_loopback(net); + if (err) + goto out_bclink; + return 0; out_bclink: @@ -94,6 +98,7 @@ static int __net_init tipc_init_net(struct net *net) static void __net_exit tipc_exit_net(struct net *net) { + tipc_detach_loopback(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); diff --git a/net/tipc/core.h b/net/tipc/core.h index 7a68e1b..60d8295 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -125,6 +125,9 @@ struct tipc_net { /* Cluster capabilities */ u16 capabilities; + + /* Tracing of node internal messages */ + struct packet_type loopback_pt; }; static inline struct tipc_net *tipc_net(struct net *net) diff --git a/net/tipc/node.c b/net/tipc/node.c index 550581d..16d251b 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, int rc; if (in_own_node(net, dnode)) { + tipc_loopback_trace(net, list); tipc_sk_rcv(net, list); return 0; } diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index f345662..e3a6ba1 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -40,6 +40,7 @@ #include "socket.h" #include "addr.h" #include "msg.h" +#include "bearer.h" #include <net/sock.h> #include <linux/module.h> @@ -608,6 +609,7 @@ static void tipc_topsrv_kern_evt(struct net *net, struct tipc_event *evt) memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); skb_queue_head_init(&evtq); __skb_queue_tail(&evtq, skb); + tipc_loopback_trace(net, &evtq); tipc_sk_rcv(net, &evtq); } -- 2.11.0 |
From: David M. <da...@da...> - 2019-08-09 05:12:03
|
From: joh...@de... Date: Wed, 7 Aug 2019 12:52:29 +1000 > From: John Rutherford <joh...@de...> > > Since node internal messages are passed directly to the socket, it is not > possible to observe those messages via tcpdump or wireshark. > > We now remedy this by making it possible to clone such messages and send > the clones to the loopback interface. The clones are dropped at reception > and have no functional role except making the traffic visible. > > The feature is enabled if network taps are active for the loopback device. > pcap filtering restrictions require the messages to be presented to the > receiving side of the loopback device. > > v3 - Function dev_nit_active used to check for network taps. > - Procedure netif_rx_ni used to send cloned messages to loopback device. > > Signed-off-by: John Rutherford <joh...@de...> > Acked-by: Jon Maloy <jon...@er...> > Acked-by: Ying Xue <yin...@wi...> Applied, thank you. |