diff options
-rw-r--r-- | include/uapi/linux/tipc.h | 30 | ||||
-rw-r--r-- | include/uapi/linux/tipc_netlink.h | 37 | ||||
-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 |
11 files changed, 445 insertions, 12 deletions
diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h index 6f71b9b41595..bf049e8fe31b 100644 --- a/include/uapi/linux/tipc.h +++ b/include/uapi/linux/tipc.h | |||
@@ -60,26 +60,48 @@ struct tipc_name_seq { | |||
60 | __u32 upper; | 60 | __u32 upper; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* TIPC Address Size, Offset, Mask specification for Z.C.N | ||
64 | */ | ||
65 | #define TIPC_NODE_BITS 12 | ||
66 | #define TIPC_CLUSTER_BITS 12 | ||
67 | #define TIPC_ZONE_BITS 8 | ||
68 | |||
69 | #define TIPC_NODE_OFFSET 0 | ||
70 | #define TIPC_CLUSTER_OFFSET TIPC_NODE_BITS | ||
71 | #define TIPC_ZONE_OFFSET (TIPC_CLUSTER_OFFSET + TIPC_CLUSTER_BITS) | ||
72 | |||
73 | #define TIPC_NODE_SIZE ((1UL << TIPC_NODE_BITS) - 1) | ||
74 | #define TIPC_CLUSTER_SIZE ((1UL << TIPC_CLUSTER_BITS) - 1) | ||
75 | #define TIPC_ZONE_SIZE ((1UL << TIPC_ZONE_BITS) - 1) | ||
76 | |||
77 | #define TIPC_NODE_MASK (TIPC_NODE_SIZE << TIPC_NODE_OFFSET) | ||
78 | #define TIPC_CLUSTER_MASK (TIPC_CLUSTER_SIZE << TIPC_CLUSTER_OFFSET) | ||
79 | #define TIPC_ZONE_MASK (TIPC_ZONE_SIZE << TIPC_ZONE_OFFSET) | ||
80 | |||
81 | #define TIPC_ZONE_CLUSTER_MASK (TIPC_ZONE_MASK | TIPC_CLUSTER_MASK) | ||
82 | |||
63 | static inline __u32 tipc_addr(unsigned int zone, | 83 | static inline __u32 tipc_addr(unsigned int zone, |
64 | unsigned int cluster, | 84 | unsigned int cluster, |
65 | unsigned int node) | 85 | unsigned int node) |
66 | { | 86 | { |
67 | return (zone << 24) | (cluster << 12) | node; | 87 | return (zone << TIPC_ZONE_OFFSET) | |
88 | (cluster << TIPC_CLUSTER_OFFSET) | | ||
89 | node; | ||
68 | } | 90 | } |
69 | 91 | ||
70 | static inline unsigned int tipc_zone(__u32 addr) | 92 | static inline unsigned int tipc_zone(__u32 addr) |
71 | { | 93 | { |
72 | return addr >> 24; | 94 | return addr >> TIPC_ZONE_OFFSET; |
73 | } | 95 | } |
74 | 96 | ||
75 | static inline unsigned int tipc_cluster(__u32 addr) | 97 | static inline unsigned int tipc_cluster(__u32 addr) |
76 | { | 98 | { |
77 | return (addr >> 12) & 0xfff; | 99 | return (addr & TIPC_CLUSTER_MASK) >> TIPC_CLUSTER_OFFSET; |
78 | } | 100 | } |
79 | 101 | ||
80 | static inline unsigned int tipc_node(__u32 addr) | 102 | static inline unsigned int tipc_node(__u32 addr) |
81 | { | 103 | { |
82 | return addr & 0xfff; | 104 | return addr & TIPC_NODE_MASK; |
83 | } | 105 | } |
84 | 106 | ||
85 | /* | 107 | /* |
diff --git a/include/uapi/linux/tipc_netlink.h b/include/uapi/linux/tipc_netlink.h index d4c8f142ba63..5f3f6d09fb79 100644 --- a/include/uapi/linux/tipc_netlink.h +++ b/include/uapi/linux/tipc_netlink.h | |||
@@ -56,6 +56,9 @@ enum { | |||
56 | TIPC_NL_NET_GET, | 56 | TIPC_NL_NET_GET, |
57 | TIPC_NL_NET_SET, | 57 | TIPC_NL_NET_SET, |
58 | TIPC_NL_NAME_TABLE_GET, | 58 | TIPC_NL_NAME_TABLE_GET, |
59 | TIPC_NL_MON_SET, | ||
60 | TIPC_NL_MON_GET, | ||
61 | TIPC_NL_MON_PEER_GET, | ||
59 | 62 | ||
60 | __TIPC_NL_CMD_MAX, | 63 | __TIPC_NL_CMD_MAX, |
61 | TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 | 64 | TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 |
@@ -72,6 +75,8 @@ enum { | |||
72 | TIPC_NLA_NODE, /* nest */ | 75 | TIPC_NLA_NODE, /* nest */ |
73 | TIPC_NLA_NET, /* nest */ | 76 | TIPC_NLA_NET, /* nest */ |
74 | TIPC_NLA_NAME_TABLE, /* nest */ | 77 | TIPC_NLA_NAME_TABLE, /* nest */ |
78 | TIPC_NLA_MON, /* nest */ | ||
79 | TIPC_NLA_MON_PEER, /* nest */ | ||
75 | 80 | ||
76 | __TIPC_NLA_MAX, | 81 | __TIPC_NLA_MAX, |
77 | TIPC_NLA_MAX = __TIPC_NLA_MAX - 1 | 82 | TIPC_NLA_MAX = __TIPC_NLA_MAX - 1 |
@@ -166,6 +171,20 @@ enum { | |||
166 | TIPC_NLA_NAME_TABLE_MAX = __TIPC_NLA_NAME_TABLE_MAX - 1 | 171 | TIPC_NLA_NAME_TABLE_MAX = __TIPC_NLA_NAME_TABLE_MAX - 1 |
167 | }; | 172 | }; |
168 | 173 | ||
174 | /* Monitor info */ | ||
175 | enum { | ||
176 | TIPC_NLA_MON_UNSPEC, | ||
177 | TIPC_NLA_MON_ACTIVATION_THRESHOLD, /* u32 */ | ||
178 | TIPC_NLA_MON_REF, /* u32 */ | ||
179 | TIPC_NLA_MON_ACTIVE, /* flag */ | ||
180 | TIPC_NLA_MON_BEARER_NAME, /* string */ | ||
181 | TIPC_NLA_MON_PEERCNT, /* u32 */ | ||
182 | TIPC_NLA_MON_LISTGEN, /* u32 */ | ||
183 | |||
184 | __TIPC_NLA_MON_MAX, | ||
185 | TIPC_NLA_MON_MAX = __TIPC_NLA_MON_MAX - 1 | ||
186 | }; | ||
187 | |||
169 | /* Publication info */ | 188 | /* Publication info */ |
170 | enum { | 189 | enum { |
171 | TIPC_NLA_PUBL_UNSPEC, | 190 | TIPC_NLA_PUBL_UNSPEC, |
@@ -182,6 +201,24 @@ enum { | |||
182 | TIPC_NLA_PUBL_MAX = __TIPC_NLA_PUBL_MAX - 1 | 201 | TIPC_NLA_PUBL_MAX = __TIPC_NLA_PUBL_MAX - 1 |
183 | }; | 202 | }; |
184 | 203 | ||
204 | /* Monitor peer info */ | ||
205 | enum { | ||
206 | TIPC_NLA_MON_PEER_UNSPEC, | ||
207 | |||
208 | TIPC_NLA_MON_PEER_ADDR, /* u32 */ | ||
209 | TIPC_NLA_MON_PEER_DOMGEN, /* u32 */ | ||
210 | TIPC_NLA_MON_PEER_APPLIED, /* u32 */ | ||
211 | TIPC_NLA_MON_PEER_UPMAP, /* u64 */ | ||
212 | TIPC_NLA_MON_PEER_MEMBERS, /* tlv */ | ||
213 | TIPC_NLA_MON_PEER_UP, /* flag */ | ||
214 | TIPC_NLA_MON_PEER_HEAD, /* flag */ | ||
215 | TIPC_NLA_MON_PEER_LOCAL, /* flag */ | ||
216 | TIPC_NLA_MON_PEER_PAD, /* flag */ | ||
217 | |||
218 | __TIPC_NLA_MON_PEER_MAX, | ||
219 | TIPC_NLA_MON_PEER_MAX = __TIPC_NLA_MON_PEER_MAX - 1 | ||
220 | }; | ||
221 | |||
185 | /* Nest, connection info */ | 222 | /* Nest, connection info */ |
186 | enum { | 223 | enum { |
187 | TIPC_NLA_CON_UNSPEC, | 224 | TIPC_NLA_CON_UNSPEC, |
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 |