diff options
author | David S. Miller <davem@davemloft.net> | 2016-07-26 17:26:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-26 17:26:43 -0400 |
commit | 2a0b9d8a1402a14fff06ed306a566025c75b2b87 (patch) | |
tree | f80b57ee326824ceda895bab95b821eb14b9b9d1 /net/tipc | |
parent | d1c2b5010d07e967d7cbcc232a86b2308d824ca3 (diff) | |
parent | cf6f7e1d51090772d5ff7355aaf0fcff17f20d1a (diff) |
Merge branch 'tipc-netlink-monitor-updates'
Parthasarathy Bhuvaragan says:
====================
tipc: netlink updates for neighbour monitor
This series contains the updates to configure and read the attributes for
neighbour monitor.
v2: rebase on top of net-next
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/addr.h | 5 | ||||
-rw-r--r-- | net/tipc/bearer.c | 25 | ||||
-rw-r--r-- | net/tipc/bearer.h | 1 | ||||
-rw-r--r-- | net/tipc/monitor.c | 152 | ||||
-rw-r--r-- | net/tipc/monitor.h | 9 | ||||
-rw-r--r-- | net/tipc/netlink.c | 27 | ||||
-rw-r--r-- | net/tipc/netlink.h | 1 | ||||
-rw-r--r-- | net/tipc/node.c | 165 | ||||
-rw-r--r-- | net/tipc/node.h | 5 |
9 files changed, 382 insertions, 8 deletions
diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 64f4004a6fac..bebb347803ce 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h | |||
@@ -43,9 +43,6 @@ | |||
43 | #include <net/netns/generic.h> | 43 | #include <net/netns/generic.h> |
44 | #include "core.h" | 44 | #include "core.h" |
45 | 45 | ||
46 | #define TIPC_ZONE_MASK 0xff000000u | ||
47 | #define TIPC_CLUSTER_MASK 0xfffff000u | ||
48 | |||
49 | static inline u32 tipc_own_addr(struct net *net) | 46 | static inline u32 tipc_own_addr(struct net *net) |
50 | { | 47 | { |
51 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 48 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
@@ -60,7 +57,7 @@ static inline u32 tipc_zone_mask(u32 addr) | |||
60 | 57 | ||
61 | static inline u32 tipc_cluster_mask(u32 addr) | 58 | static inline u32 tipc_cluster_mask(u32 addr) |
62 | { | 59 | { |
63 | return addr & TIPC_CLUSTER_MASK; | 60 | return addr & TIPC_ZONE_CLUSTER_MASK; |
64 | } | 61 | } |
65 | 62 | ||
66 | u32 tipc_own_addr(struct net *net); | 63 | u32 tipc_own_addr(struct net *net); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 4131d5a86f55..65b1bbf133bd 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -171,6 +171,27 @@ struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name) | |||
171 | return NULL; | 171 | return NULL; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* tipc_bearer_get_name - get the bearer name from its id. | ||
175 | * @net: network namespace | ||
176 | * @name: a pointer to the buffer where the name will be stored. | ||
177 | * @bearer_id: the id to get the name from. | ||
178 | */ | ||
179 | int tipc_bearer_get_name(struct net *net, char *name, u32 bearer_id) | ||
180 | { | ||
181 | struct tipc_net *tn = tipc_net(net); | ||
182 | struct tipc_bearer *b; | ||
183 | |||
184 | if (bearer_id >= MAX_BEARERS) | ||
185 | return -EINVAL; | ||
186 | |||
187 | b = rtnl_dereference(tn->bearer_list[bearer_id]); | ||
188 | if (!b) | ||
189 | return -EINVAL; | ||
190 | |||
191 | strcpy(name, b->name); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
174 | void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest) | 195 | void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest) |
175 | { | 196 | { |
176 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 197 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
@@ -225,7 +246,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, | |||
225 | if (tipc_addr_domain_valid(disc_domain) && | 246 | if (tipc_addr_domain_valid(disc_domain) && |
226 | (disc_domain != tn->own_addr)) { | 247 | (disc_domain != tn->own_addr)) { |
227 | if (tipc_in_scope(disc_domain, tn->own_addr)) { | 248 | if (tipc_in_scope(disc_domain, tn->own_addr)) { |
228 | disc_domain = tn->own_addr & TIPC_CLUSTER_MASK; | 249 | disc_domain = tn->own_addr & TIPC_ZONE_CLUSTER_MASK; |
229 | res = 0; /* accept any node in own cluster */ | 250 | res = 0; /* accept any node in own cluster */ |
230 | } else if (in_own_cluster_exact(net, disc_domain)) | 251 | } else if (in_own_cluster_exact(net, disc_domain)) |
231 | res = 0; /* accept specified node in own cluster */ | 252 | res = 0; /* accept specified node in own cluster */ |
@@ -832,7 +853,7 @@ int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) | |||
832 | u32 prio; | 853 | u32 prio; |
833 | 854 | ||
834 | prio = TIPC_MEDIA_LINK_PRI; | 855 | prio = TIPC_MEDIA_LINK_PRI; |
835 | domain = tn->own_addr & TIPC_CLUSTER_MASK; | 856 | domain = tn->own_addr & TIPC_ZONE_CLUSTER_MASK; |
836 | 857 | ||
837 | if (!info->attrs[TIPC_NLA_BEARER]) | 858 | if (!info->attrs[TIPC_NLA_BEARER]) |
838 | return -EINVAL; | 859 | return -EINVAL; |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index f1e6db5e6345..43757f1f9cb3 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -197,6 +197,7 @@ int tipc_l2_send_msg(struct net *net, struct sk_buff *buf, | |||
197 | void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest); | 197 | void tipc_bearer_add_dest(struct net *net, u32 bearer_id, u32 dest); |
198 | void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest); | 198 | void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest); |
199 | struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name); | 199 | struct tipc_bearer *tipc_bearer_find(struct net *net, const char *name); |
200 | int tipc_bearer_get_name(struct net *net, char *name, u32 bearer_id); | ||
200 | struct tipc_media *tipc_media_find(const char *name); | 201 | struct tipc_media *tipc_media_find(const char *name); |
201 | void tipc_bearer_reset_all(struct net *net); | 202 | void tipc_bearer_reset_all(struct net *net); |
202 | int tipc_bearer_setup(void); | 203 | int tipc_bearer_setup(void); |
diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c index 0d489e81fcca..be70a57c1ff9 100644 --- a/net/tipc/monitor.c +++ b/net/tipc/monitor.c | |||
@@ -33,9 +33,11 @@ | |||
33 | * POSSIBILITY OF SUCH DAMAGE. | 33 | * POSSIBILITY OF SUCH DAMAGE. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <net/genetlink.h> | ||
36 | #include "core.h" | 37 | #include "core.h" |
37 | #include "addr.h" | 38 | #include "addr.h" |
38 | #include "monitor.h" | 39 | #include "monitor.h" |
40 | #include "bearer.h" | ||
39 | 41 | ||
40 | #define MAX_MON_DOMAIN 64 | 42 | #define MAX_MON_DOMAIN 64 |
41 | #define MON_TIMEOUT 120000 | 43 | #define MON_TIMEOUT 120000 |
@@ -649,3 +651,153 @@ void tipc_mon_delete(struct net *net, int bearer_id) | |||
649 | kfree(self); | 651 | kfree(self); |
650 | kfree(mon); | 652 | kfree(mon); |
651 | } | 653 | } |
654 | |||
655 | int tipc_nl_monitor_set_threshold(struct net *net, u32 cluster_size) | ||
656 | { | ||
657 | struct tipc_net *tn = tipc_net(net); | ||
658 | |||
659 | if (cluster_size > TIPC_CLUSTER_SIZE) | ||
660 | return -EINVAL; | ||
661 | |||
662 | tn->mon_threshold = cluster_size; | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | int tipc_nl_monitor_get_threshold(struct net *net) | ||
668 | { | ||
669 | struct tipc_net *tn = tipc_net(net); | ||
670 | |||
671 | return tn->mon_threshold; | ||
672 | } | ||
673 | |||
674 | int __tipc_nl_add_monitor_peer(struct tipc_peer *peer, struct tipc_nl_msg *msg) | ||
675 | { | ||
676 | struct tipc_mon_domain *dom = peer->domain; | ||
677 | struct nlattr *attrs; | ||
678 | void *hdr; | ||
679 | |||
680 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | ||
681 | NLM_F_MULTI, TIPC_NL_MON_PEER_GET); | ||
682 | if (!hdr) | ||
683 | return -EMSGSIZE; | ||
684 | |||
685 | attrs = nla_nest_start(msg->skb, TIPC_NLA_MON_PEER); | ||
686 | if (!attrs) | ||
687 | goto msg_full; | ||
688 | |||
689 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEER_ADDR, peer->addr)) | ||
690 | goto attr_msg_full; | ||
691 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEER_APPLIED, peer->applied)) | ||
692 | goto attr_msg_full; | ||
693 | |||
694 | if (peer->is_up) | ||
695 | if (nla_put_flag(msg->skb, TIPC_NLA_MON_PEER_UP)) | ||
696 | goto attr_msg_full; | ||
697 | if (peer->is_local) | ||
698 | if (nla_put_flag(msg->skb, TIPC_NLA_MON_PEER_LOCAL)) | ||
699 | goto attr_msg_full; | ||
700 | if (peer->is_head) | ||
701 | if (nla_put_flag(msg->skb, TIPC_NLA_MON_PEER_HEAD)) | ||
702 | goto attr_msg_full; | ||
703 | |||
704 | if (dom) { | ||
705 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEER_DOMGEN, dom->gen)) | ||
706 | goto attr_msg_full; | ||
707 | if (nla_put_u64_64bit(msg->skb, TIPC_NLA_MON_PEER_UPMAP, | ||
708 | dom->up_map, TIPC_NLA_MON_PEER_PAD)) | ||
709 | goto attr_msg_full; | ||
710 | if (nla_put(msg->skb, TIPC_NLA_MON_PEER_MEMBERS, | ||
711 | dom->member_cnt * sizeof(u32), &dom->members)) | ||
712 | goto attr_msg_full; | ||
713 | } | ||
714 | |||
715 | nla_nest_end(msg->skb, attrs); | ||
716 | genlmsg_end(msg->skb, hdr); | ||
717 | return 0; | ||
718 | |||
719 | attr_msg_full: | ||
720 | nla_nest_cancel(msg->skb, attrs); | ||
721 | msg_full: | ||
722 | genlmsg_cancel(msg->skb, hdr); | ||
723 | |||
724 | return -EMSGSIZE; | ||
725 | } | ||
726 | |||
727 | int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg, | ||
728 | u32 bearer_id, u32 *prev_node) | ||
729 | { | ||
730 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
731 | struct tipc_peer *peer = mon->self; | ||
732 | |||
733 | if (!mon) | ||
734 | return -EINVAL; | ||
735 | |||
736 | read_lock_bh(&mon->lock); | ||
737 | do { | ||
738 | if (*prev_node) { | ||
739 | if (peer->addr == *prev_node) | ||
740 | *prev_node = 0; | ||
741 | else | ||
742 | continue; | ||
743 | } | ||
744 | if (__tipc_nl_add_monitor_peer(peer, msg)) { | ||
745 | *prev_node = peer->addr; | ||
746 | read_unlock_bh(&mon->lock); | ||
747 | return -EMSGSIZE; | ||
748 | } | ||
749 | } while ((peer = peer_nxt(peer)) != mon->self); | ||
750 | read_unlock_bh(&mon->lock); | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg, | ||
756 | u32 bearer_id) | ||
757 | { | ||
758 | struct tipc_monitor *mon = tipc_monitor(net, bearer_id); | ||
759 | char bearer_name[TIPC_MAX_BEARER_NAME]; | ||
760 | struct nlattr *attrs; | ||
761 | void *hdr; | ||
762 | int ret; | ||
763 | |||
764 | ret = tipc_bearer_get_name(net, bearer_name, bearer_id); | ||
765 | if (ret || !mon) | ||
766 | return -EINVAL; | ||
767 | |||
768 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | ||
769 | NLM_F_MULTI, TIPC_NL_MON_GET); | ||
770 | if (!hdr) | ||
771 | return -EMSGSIZE; | ||
772 | |||
773 | attrs = nla_nest_start(msg->skb, TIPC_NLA_MON); | ||
774 | if (!attrs) | ||
775 | goto msg_full; | ||
776 | |||
777 | read_lock_bh(&mon->lock); | ||
778 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_REF, bearer_id)) | ||
779 | goto attr_msg_full; | ||
780 | if (tipc_mon_is_active(net, mon)) | ||
781 | if (nla_put_flag(msg->skb, TIPC_NLA_MON_ACTIVE)) | ||
782 | goto attr_msg_full; | ||
783 | if (nla_put_string(msg->skb, TIPC_NLA_MON_BEARER_NAME, bearer_name)) | ||
784 | goto attr_msg_full; | ||
785 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEERCNT, mon->peer_cnt)) | ||
786 | goto attr_msg_full; | ||
787 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_LISTGEN, mon->list_gen)) | ||
788 | goto attr_msg_full; | ||
789 | |||
790 | read_unlock_bh(&mon->lock); | ||
791 | nla_nest_end(msg->skb, attrs); | ||
792 | genlmsg_end(msg->skb, hdr); | ||
793 | |||
794 | return 0; | ||
795 | |||
796 | attr_msg_full: | ||
797 | nla_nest_cancel(msg->skb, attrs); | ||
798 | msg_full: | ||
799 | genlmsg_cancel(msg->skb, hdr); | ||
800 | read_unlock_bh(&mon->lock); | ||
801 | |||
802 | return -EMSGSIZE; | ||
803 | } | ||
diff --git a/net/tipc/monitor.h b/net/tipc/monitor.h index 598459cbed5d..2a21b93e0d04 100644 --- a/net/tipc/monitor.h +++ b/net/tipc/monitor.h | |||
@@ -36,6 +36,8 @@ | |||
36 | #ifndef _TIPC_MONITOR_H | 36 | #ifndef _TIPC_MONITOR_H |
37 | #define _TIPC_MONITOR_H | 37 | #define _TIPC_MONITOR_H |
38 | 38 | ||
39 | #include "netlink.h" | ||
40 | |||
39 | /* struct tipc_mon_state: link instance's cache of monitor list and domain state | 41 | /* struct tipc_mon_state: link instance's cache of monitor list and domain state |
40 | * @list_gen: current generation of this node's monitor list | 42 | * @list_gen: current generation of this node's monitor list |
41 | * @gen: current generation of this node's local domain | 43 | * @gen: current generation of this node's local domain |
@@ -69,5 +71,12 @@ void tipc_mon_get_state(struct net *net, u32 addr, | |||
69 | int bearer_id); | 71 | int bearer_id); |
70 | void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id); | 72 | void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id); |
71 | 73 | ||
74 | int tipc_nl_monitor_set_threshold(struct net *net, u32 cluster_size); | ||
75 | int tipc_nl_monitor_get_threshold(struct net *net); | ||
76 | int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg, | ||
77 | u32 bearer_id); | ||
78 | int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg, | ||
79 | u32 bearer_id, u32 *prev_node); | ||
80 | |||
72 | extern const int tipc_max_domain_size; | 81 | extern const int tipc_max_domain_size; |
73 | #endif | 82 | #endif |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 56935df2167a..a84daec0afe9 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -52,7 +52,8 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { | |||
52 | [TIPC_NLA_MEDIA] = { .type = NLA_NESTED, }, | 52 | [TIPC_NLA_MEDIA] = { .type = NLA_NESTED, }, |
53 | [TIPC_NLA_NODE] = { .type = NLA_NESTED, }, | 53 | [TIPC_NLA_NODE] = { .type = NLA_NESTED, }, |
54 | [TIPC_NLA_NET] = { .type = NLA_NESTED, }, | 54 | [TIPC_NLA_NET] = { .type = NLA_NESTED, }, |
55 | [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, } | 55 | [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, }, |
56 | [TIPC_NLA_MON] = { .type = NLA_NESTED, }, | ||
56 | }; | 57 | }; |
57 | 58 | ||
58 | const struct nla_policy | 59 | const struct nla_policy |
@@ -61,6 +62,12 @@ tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = { | |||
61 | [TIPC_NLA_NAME_TABLE_PUBL] = { .type = NLA_NESTED } | 62 | [TIPC_NLA_NAME_TABLE_PUBL] = { .type = NLA_NESTED } |
62 | }; | 63 | }; |
63 | 64 | ||
65 | const struct nla_policy tipc_nl_monitor_policy[TIPC_NLA_MON_MAX + 1] = { | ||
66 | [TIPC_NLA_MON_UNSPEC] = { .type = NLA_UNSPEC }, | ||
67 | [TIPC_NLA_MON_REF] = { .type = NLA_U32 }, | ||
68 | [TIPC_NLA_MON_ACTIVATION_THRESHOLD] = { .type = NLA_U32 }, | ||
69 | }; | ||
70 | |||
64 | const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { | 71 | const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { |
65 | [TIPC_NLA_SOCK_UNSPEC] = { .type = NLA_UNSPEC }, | 72 | [TIPC_NLA_SOCK_UNSPEC] = { .type = NLA_UNSPEC }, |
66 | [TIPC_NLA_SOCK_ADDR] = { .type = NLA_U32 }, | 73 | [TIPC_NLA_SOCK_ADDR] = { .type = NLA_U32 }, |
@@ -214,7 +221,23 @@ static const struct genl_ops tipc_genl_v2_ops[] = { | |||
214 | .cmd = TIPC_NL_NAME_TABLE_GET, | 221 | .cmd = TIPC_NL_NAME_TABLE_GET, |
215 | .dumpit = tipc_nl_name_table_dump, | 222 | .dumpit = tipc_nl_name_table_dump, |
216 | .policy = tipc_nl_policy, | 223 | .policy = tipc_nl_policy, |
217 | } | 224 | }, |
225 | { | ||
226 | .cmd = TIPC_NL_MON_SET, | ||
227 | .doit = tipc_nl_node_set_monitor, | ||
228 | .policy = tipc_nl_policy, | ||
229 | }, | ||
230 | { | ||
231 | .cmd = TIPC_NL_MON_GET, | ||
232 | .doit = tipc_nl_node_get_monitor, | ||
233 | .dumpit = tipc_nl_node_dump_monitor, | ||
234 | .policy = tipc_nl_policy, | ||
235 | }, | ||
236 | { | ||
237 | .cmd = TIPC_NL_MON_PEER_GET, | ||
238 | .dumpit = tipc_nl_node_dump_monitor_peer, | ||
239 | .policy = tipc_nl_policy, | ||
240 | }, | ||
218 | }; | 241 | }; |
219 | 242 | ||
220 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) | 243 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr) |
diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h index ed1dbcb4afbd..4ba0ad422110 100644 --- a/net/tipc/netlink.h +++ b/net/tipc/netlink.h | |||
@@ -55,6 +55,7 @@ extern const struct nla_policy tipc_nl_prop_policy[]; | |||
55 | extern const struct nla_policy tipc_nl_bearer_policy[]; | 55 | extern const struct nla_policy tipc_nl_bearer_policy[]; |
56 | extern const struct nla_policy tipc_nl_media_policy[]; | 56 | extern const struct nla_policy tipc_nl_media_policy[]; |
57 | extern const struct nla_policy tipc_nl_udp_policy[]; | 57 | extern const struct nla_policy tipc_nl_udp_policy[]; |
58 | extern const struct nla_policy tipc_nl_monitor_policy[]; | ||
58 | 59 | ||
59 | int tipc_netlink_start(void); | 60 | int tipc_netlink_start(void); |
60 | int tipc_netlink_compat_start(void); | 61 | int tipc_netlink_compat_start(void); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 95cc78b51532..21974191e425 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -1928,3 +1928,168 @@ out: | |||
1928 | 1928 | ||
1929 | return skb->len; | 1929 | return skb->len; |
1930 | } | 1930 | } |
1931 | |||
1932 | int tipc_nl_node_set_monitor(struct sk_buff *skb, struct genl_info *info) | ||
1933 | { | ||
1934 | struct nlattr *attrs[TIPC_NLA_MON_MAX + 1]; | ||
1935 | struct net *net = sock_net(skb->sk); | ||
1936 | int err; | ||
1937 | |||
1938 | if (!info->attrs[TIPC_NLA_MON]) | ||
1939 | return -EINVAL; | ||
1940 | |||
1941 | err = nla_parse_nested(attrs, TIPC_NLA_MON_MAX, | ||
1942 | info->attrs[TIPC_NLA_MON], | ||
1943 | tipc_nl_monitor_policy); | ||
1944 | if (err) | ||
1945 | return err; | ||
1946 | |||
1947 | if (attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]) { | ||
1948 | u32 val; | ||
1949 | |||
1950 | val = nla_get_u32(attrs[TIPC_NLA_MON_ACTIVATION_THRESHOLD]); | ||
1951 | err = tipc_nl_monitor_set_threshold(net, val); | ||
1952 | if (err) | ||
1953 | return err; | ||
1954 | } | ||
1955 | |||
1956 | return 0; | ||
1957 | } | ||
1958 | |||
1959 | static int __tipc_nl_add_monitor_prop(struct net *net, struct tipc_nl_msg *msg) | ||
1960 | { | ||
1961 | struct nlattr *attrs; | ||
1962 | void *hdr; | ||
1963 | u32 val; | ||
1964 | |||
1965 | hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, | ||
1966 | 0, TIPC_NL_MON_GET); | ||
1967 | if (!hdr) | ||
1968 | return -EMSGSIZE; | ||
1969 | |||
1970 | attrs = nla_nest_start(msg->skb, TIPC_NLA_MON); | ||
1971 | if (!attrs) | ||
1972 | goto msg_full; | ||
1973 | |||
1974 | val = tipc_nl_monitor_get_threshold(net); | ||
1975 | |||
1976 | if (nla_put_u32(msg->skb, TIPC_NLA_MON_ACTIVATION_THRESHOLD, val)) | ||
1977 | goto attr_msg_full; | ||
1978 | |||
1979 | nla_nest_end(msg->skb, attrs); | ||
1980 | genlmsg_end(msg->skb, hdr); | ||
1981 | |||
1982 | return 0; | ||
1983 | |||
1984 | attr_msg_full: | ||
1985 | nla_nest_cancel(msg->skb, attrs); | ||
1986 | msg_full: | ||
1987 | genlmsg_cancel(msg->skb, hdr); | ||
1988 | |||
1989 | return -EMSGSIZE; | ||
1990 | } | ||
1991 | |||
1992 | int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info) | ||
1993 | { | ||
1994 | struct net *net = sock_net(skb->sk); | ||
1995 | struct tipc_nl_msg msg; | ||
1996 | int err; | ||
1997 | |||
1998 | msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
1999 | msg.portid = info->snd_portid; | ||
2000 | msg.seq = info->snd_seq; | ||
2001 | |||
2002 | err = __tipc_nl_add_monitor_prop(net, &msg); | ||
2003 | if (err) { | ||
2004 | nlmsg_free(msg.skb); | ||
2005 | return err; | ||
2006 | } | ||
2007 | |||
2008 | return genlmsg_reply(msg.skb, info); | ||
2009 | } | ||
2010 | |||
2011 | int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb) | ||
2012 | { | ||
2013 | struct net *net = sock_net(skb->sk); | ||
2014 | u32 prev_bearer = cb->args[0]; | ||
2015 | struct tipc_nl_msg msg; | ||
2016 | int err; | ||
2017 | int i; | ||
2018 | |||
2019 | if (prev_bearer == MAX_BEARERS) | ||
2020 | return 0; | ||
2021 | |||
2022 | msg.skb = skb; | ||
2023 | msg.portid = NETLINK_CB(cb->skb).portid; | ||
2024 | msg.seq = cb->nlh->nlmsg_seq; | ||
2025 | |||
2026 | rtnl_lock(); | ||
2027 | for (i = prev_bearer; i < MAX_BEARERS; i++) { | ||
2028 | prev_bearer = i; | ||
2029 | err = __tipc_nl_add_monitor(net, &msg, prev_bearer); | ||
2030 | if (err) | ||
2031 | goto out; | ||
2032 | } | ||
2033 | |||
2034 | out: | ||
2035 | rtnl_unlock(); | ||
2036 | cb->args[0] = prev_bearer; | ||
2037 | |||
2038 | return skb->len; | ||
2039 | } | ||
2040 | |||
2041 | int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb, | ||
2042 | struct netlink_callback *cb) | ||
2043 | { | ||
2044 | struct net *net = sock_net(skb->sk); | ||
2045 | u32 prev_node = cb->args[1]; | ||
2046 | u32 bearer_id = cb->args[2]; | ||
2047 | int done = cb->args[0]; | ||
2048 | struct tipc_nl_msg msg; | ||
2049 | int err; | ||
2050 | |||
2051 | if (!prev_node) { | ||
2052 | struct nlattr **attrs; | ||
2053 | struct nlattr *mon[TIPC_NLA_MON_MAX + 1]; | ||
2054 | |||
2055 | err = tipc_nlmsg_parse(cb->nlh, &attrs); | ||
2056 | if (err) | ||
2057 | return err; | ||
2058 | |||
2059 | if (!attrs[TIPC_NLA_MON]) | ||
2060 | return -EINVAL; | ||
2061 | |||
2062 | err = nla_parse_nested(mon, TIPC_NLA_MON_MAX, | ||
2063 | attrs[TIPC_NLA_MON], | ||
2064 | tipc_nl_monitor_policy); | ||
2065 | if (err) | ||
2066 | return err; | ||
2067 | |||
2068 | if (!mon[TIPC_NLA_MON_REF]) | ||
2069 | return -EINVAL; | ||
2070 | |||
2071 | bearer_id = nla_get_u32(mon[TIPC_NLA_MON_REF]); | ||
2072 | |||
2073 | if (bearer_id >= MAX_BEARERS) | ||
2074 | return -EINVAL; | ||
2075 | } | ||
2076 | |||
2077 | if (done) | ||
2078 | return 0; | ||
2079 | |||
2080 | msg.skb = skb; | ||
2081 | msg.portid = NETLINK_CB(cb->skb).portid; | ||
2082 | msg.seq = cb->nlh->nlmsg_seq; | ||
2083 | |||
2084 | rtnl_lock(); | ||
2085 | err = tipc_nl_add_monitor_peer(net, &msg, bearer_id, &prev_node); | ||
2086 | if (!err) | ||
2087 | done = 1; | ||
2088 | |||
2089 | rtnl_unlock(); | ||
2090 | cb->args[0] = done; | ||
2091 | cb->args[1] = prev_node; | ||
2092 | cb->args[2] = bearer_id; | ||
2093 | |||
2094 | return skb->len; | ||
2095 | } | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h index 8264b3d97dc4..d69fdfcc0ec9 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -78,4 +78,9 @@ int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info); | |||
78 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info); | 78 | int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info); |
79 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info); | 79 | int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info); |
80 | 80 | ||
81 | int tipc_nl_node_set_monitor(struct sk_buff *skb, struct genl_info *info); | ||
82 | int tipc_nl_node_get_monitor(struct sk_buff *skb, struct genl_info *info); | ||
83 | int tipc_nl_node_dump_monitor(struct sk_buff *skb, struct netlink_callback *cb); | ||
84 | int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb, | ||
85 | struct netlink_callback *cb); | ||
81 | #endif | 86 | #endif |