diff options
author | Richard Alpe <richard.alpe@ericsson.com> | 2015-02-09 03:50:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-09 16:20:48 -0500 |
commit | 44a8ae94fd5525aa06a8c71cb52efbc418fb8b7c (patch) | |
tree | 7ccc0602ea66ed8b811a423fbcd0f7745127067d | |
parent | 1817877b3cd7b4dc73e4a1514d5f48eaa3989ec9 (diff) |
tipc: convert legacy nl name table dump to nl compat
Add functionality for printing a dump header and convert
TIPC_CMD_SHOW_NAME_TABLE to compat dumpit.
Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/tipc/config.c | 4 | ||||
-rw-r--r-- | net/tipc/name_table.c | 184 | ||||
-rw-r--r-- | net/tipc/name_table.h | 2 | ||||
-rw-r--r-- | net/tipc/netlink_compat.c | 101 |
4 files changed, 101 insertions, 190 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c index 11c16d191fa2..7b053fcc4b87 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -209,10 +209,6 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, | |||
209 | rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, | 209 | rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area, |
210 | req_tlv_space); | 210 | req_tlv_space); |
211 | break; | 211 | break; |
212 | case TIPC_CMD_SHOW_NAME_TABLE: | ||
213 | rep_tlv_buf = tipc_nametbl_get(net, req_tlv_area, | ||
214 | req_tlv_space); | ||
215 | break; | ||
216 | case TIPC_CMD_GET_MEDIA_NAMES: | 212 | case TIPC_CMD_GET_MEDIA_NAMES: |
217 | rep_tlv_buf = tipc_media_get_names(); | 213 | rep_tlv_buf = tipc_media_get_names(); |
218 | break; | 214 | break; |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 2251912264a2..c8eaa2afe875 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -773,190 +773,6 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) | |||
773 | spin_unlock_bh(&tn->nametbl_lock); | 773 | spin_unlock_bh(&tn->nametbl_lock); |
774 | } | 774 | } |
775 | 775 | ||
776 | /** | ||
777 | * subseq_list - print specified sub-sequence contents into the given buffer | ||
778 | */ | ||
779 | static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, | ||
780 | u32 index) | ||
781 | { | ||
782 | char portIdStr[27]; | ||
783 | const char *scope_str[] = {"", " zone", " cluster", " node"}; | ||
784 | struct publication *publ; | ||
785 | struct name_info *info; | ||
786 | int ret; | ||
787 | |||
788 | ret = tipc_snprintf(buf, len, "%-10u %-10u ", sseq->lower, sseq->upper); | ||
789 | |||
790 | if (depth == 2) { | ||
791 | ret += tipc_snprintf(buf - ret, len + ret, "\n"); | ||
792 | return ret; | ||
793 | } | ||
794 | |||
795 | info = sseq->info; | ||
796 | |||
797 | list_for_each_entry(publ, &info->zone_list, zone_list) { | ||
798 | sprintf(portIdStr, "<%u.%u.%u:%u>", | ||
799 | tipc_zone(publ->node), tipc_cluster(publ->node), | ||
800 | tipc_node(publ->node), publ->ref); | ||
801 | ret += tipc_snprintf(buf + ret, len - ret, "%-26s ", portIdStr); | ||
802 | if (depth > 3) { | ||
803 | ret += tipc_snprintf(buf + ret, len - ret, "%-10u %s", | ||
804 | publ->key, scope_str[publ->scope]); | ||
805 | } | ||
806 | if (!list_is_last(&publ->zone_list, &info->zone_list)) | ||
807 | ret += tipc_snprintf(buf + ret, len - ret, | ||
808 | "\n%33s", " "); | ||
809 | } | ||
810 | |||
811 | ret += tipc_snprintf(buf + ret, len - ret, "\n"); | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | /** | ||
816 | * nameseq_list - print specified name sequence contents into the given buffer | ||
817 | */ | ||
818 | static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth, | ||
819 | u32 type, u32 lowbound, u32 upbound, u32 index) | ||
820 | { | ||
821 | struct sub_seq *sseq; | ||
822 | char typearea[11]; | ||
823 | int ret = 0; | ||
824 | |||
825 | if (seq->first_free == 0) | ||
826 | return 0; | ||
827 | |||
828 | sprintf(typearea, "%-10u", seq->type); | ||
829 | |||
830 | if (depth == 1) { | ||
831 | ret += tipc_snprintf(buf, len, "%s\n", typearea); | ||
832 | return ret; | ||
833 | } | ||
834 | |||
835 | for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
836 | if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { | ||
837 | ret += tipc_snprintf(buf + ret, len - ret, "%s ", | ||
838 | typearea); | ||
839 | spin_lock_bh(&seq->lock); | ||
840 | ret += subseq_list(sseq, buf + ret, len - ret, | ||
841 | depth, index); | ||
842 | spin_unlock_bh(&seq->lock); | ||
843 | sprintf(typearea, "%10s", " "); | ||
844 | } | ||
845 | } | ||
846 | return ret; | ||
847 | } | ||
848 | |||
849 | /** | ||
850 | * nametbl_header - print name table header into the given buffer | ||
851 | */ | ||
852 | static int nametbl_header(char *buf, int len, u32 depth) | ||
853 | { | ||
854 | const char *header[] = { | ||
855 | "Type ", | ||
856 | "Lower Upper ", | ||
857 | "Port Identity ", | ||
858 | "Publication Scope" | ||
859 | }; | ||
860 | |||
861 | int i; | ||
862 | int ret = 0; | ||
863 | |||
864 | if (depth > 4) | ||
865 | depth = 4; | ||
866 | for (i = 0; i < depth; i++) | ||
867 | ret += tipc_snprintf(buf + ret, len - ret, header[i]); | ||
868 | ret += tipc_snprintf(buf + ret, len - ret, "\n"); | ||
869 | return ret; | ||
870 | } | ||
871 | |||
872 | /** | ||
873 | * nametbl_list - print specified name table contents into the given buffer | ||
874 | */ | ||
875 | static int nametbl_list(struct net *net, char *buf, int len, u32 depth_info, | ||
876 | u32 type, u32 lowbound, u32 upbound) | ||
877 | { | ||
878 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
879 | struct hlist_head *seq_head; | ||
880 | struct name_seq *seq; | ||
881 | int all_types; | ||
882 | int ret = 0; | ||
883 | u32 depth; | ||
884 | u32 i; | ||
885 | |||
886 | all_types = (depth_info & TIPC_NTQ_ALLTYPES); | ||
887 | depth = (depth_info & ~TIPC_NTQ_ALLTYPES); | ||
888 | |||
889 | if (depth == 0) | ||
890 | return 0; | ||
891 | |||
892 | if (all_types) { | ||
893 | /* display all entries in name table to specified depth */ | ||
894 | ret += nametbl_header(buf, len, depth); | ||
895 | lowbound = 0; | ||
896 | upbound = ~0; | ||
897 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { | ||
898 | seq_head = &tn->nametbl->seq_hlist[i]; | ||
899 | hlist_for_each_entry_rcu(seq, seq_head, ns_list) { | ||
900 | ret += nameseq_list(seq, buf + ret, len - ret, | ||
901 | depth, seq->type, | ||
902 | lowbound, upbound, i); | ||
903 | } | ||
904 | } | ||
905 | } else { | ||
906 | /* display only the sequence that matches the specified type */ | ||
907 | if (upbound < lowbound) { | ||
908 | ret += tipc_snprintf(buf + ret, len - ret, | ||
909 | "invalid name sequence specified\n"); | ||
910 | return ret; | ||
911 | } | ||
912 | ret += nametbl_header(buf + ret, len - ret, depth); | ||
913 | i = hash(type); | ||
914 | seq_head = &tn->nametbl->seq_hlist[i]; | ||
915 | hlist_for_each_entry_rcu(seq, seq_head, ns_list) { | ||
916 | if (seq->type == type) { | ||
917 | ret += nameseq_list(seq, buf + ret, len - ret, | ||
918 | depth, type, | ||
919 | lowbound, upbound, i); | ||
920 | break; | ||
921 | } | ||
922 | } | ||
923 | } | ||
924 | return ret; | ||
925 | } | ||
926 | |||
927 | struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area, | ||
928 | int req_tlv_space) | ||
929 | { | ||
930 | struct sk_buff *buf; | ||
931 | struct tipc_name_table_query *argv; | ||
932 | struct tlv_desc *rep_tlv; | ||
933 | char *pb; | ||
934 | int pb_len; | ||
935 | int str_len; | ||
936 | |||
937 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) | ||
938 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
939 | |||
940 | buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN)); | ||
941 | if (!buf) | ||
942 | return NULL; | ||
943 | |||
944 | rep_tlv = (struct tlv_desc *)buf->data; | ||
945 | pb = TLV_DATA(rep_tlv); | ||
946 | pb_len = ULTRA_STRING_MAX_LEN; | ||
947 | argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); | ||
948 | rcu_read_lock(); | ||
949 | str_len = nametbl_list(net, pb, pb_len, ntohl(argv->depth), | ||
950 | ntohl(argv->type), | ||
951 | ntohl(argv->lowbound), ntohl(argv->upbound)); | ||
952 | rcu_read_unlock(); | ||
953 | str_len += 1; /* for "\0" */ | ||
954 | skb_put(buf, TLV_SPACE(str_len)); | ||
955 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
956 | |||
957 | return buf; | ||
958 | } | ||
959 | |||
960 | int tipc_nametbl_init(struct net *net) | 776 | int tipc_nametbl_init(struct net *net) |
961 | { | 777 | { |
962 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 778 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 0304ddc6b101..1524a73830f7 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h | |||
@@ -97,8 +97,6 @@ struct name_table { | |||
97 | 97 | ||
98 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); | 98 | int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); |
99 | 99 | ||
100 | struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area, | ||
101 | int req_tlv_space); | ||
102 | u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); | 100 | u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); |
103 | int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, | 101 | int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, |
104 | u32 limit, struct tipc_plist *dports); | 102 | u32 limit, struct tipc_plist *dports); |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 02461233b6d8..40c24ea31231 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "config.h" | 35 | #include "config.h" |
36 | #include "bearer.h" | 36 | #include "bearer.h" |
37 | #include "link.h" | 37 | #include "link.h" |
38 | #include "name_table.h" | ||
38 | #include <net/genetlink.h> | 39 | #include <net/genetlink.h> |
39 | #include <linux/tipc_config.h> | 40 | #include <linux/tipc_config.h> |
40 | 41 | ||
@@ -58,6 +59,7 @@ struct tipc_nl_compat_msg { | |||
58 | }; | 59 | }; |
59 | 60 | ||
60 | struct tipc_nl_compat_cmd_dump { | 61 | struct tipc_nl_compat_cmd_dump { |
62 | int (*header)(struct tipc_nl_compat_msg *); | ||
61 | int (*dumpit)(struct sk_buff *, struct netlink_callback *); | 63 | int (*dumpit)(struct sk_buff *, struct netlink_callback *); |
62 | int (*format)(struct tipc_nl_compat_msg *msg, struct nlattr **attrs); | 64 | int (*format)(struct tipc_nl_compat_msg *msg, struct nlattr **attrs); |
63 | }; | 65 | }; |
@@ -246,6 +248,9 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, | |||
246 | if (msg->rep_type) | 248 | if (msg->rep_type) |
247 | tipc_tlv_init(msg->rep, msg->rep_type); | 249 | tipc_tlv_init(msg->rep, msg->rep_type); |
248 | 250 | ||
251 | if (cmd->header) | ||
252 | (*cmd->header)(msg); | ||
253 | |||
249 | arg = nlmsg_new(0, GFP_KERNEL); | 254 | arg = nlmsg_new(0, GFP_KERNEL); |
250 | if (!arg) { | 255 | if (!arg) { |
251 | kfree_skb(msg->rep); | 256 | kfree_skb(msg->rep); |
@@ -626,6 +631,93 @@ static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb, | |||
626 | return 0; | 631 | return 0; |
627 | } | 632 | } |
628 | 633 | ||
634 | static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg) | ||
635 | { | ||
636 | int i; | ||
637 | u32 depth; | ||
638 | struct tipc_name_table_query *ntq; | ||
639 | static const char * const header[] = { | ||
640 | "Type ", | ||
641 | "Lower Upper ", | ||
642 | "Port Identity ", | ||
643 | "Publication Scope" | ||
644 | }; | ||
645 | |||
646 | ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); | ||
647 | |||
648 | depth = ntohl(ntq->depth); | ||
649 | |||
650 | if (depth > 4) | ||
651 | depth = 4; | ||
652 | for (i = 0; i < depth; i++) | ||
653 | tipc_tlv_sprintf(msg->rep, header[i]); | ||
654 | tipc_tlv_sprintf(msg->rep, "\n"); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg, | ||
660 | struct nlattr **attrs) | ||
661 | { | ||
662 | char port_str[27]; | ||
663 | struct tipc_name_table_query *ntq; | ||
664 | struct nlattr *nt[TIPC_NLA_NAME_TABLE_MAX + 1]; | ||
665 | struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1]; | ||
666 | u32 node, depth, type, lowbound, upbound; | ||
667 | static const char * const scope_str[] = {"", " zone", " cluster", | ||
668 | " node"}; | ||
669 | |||
670 | nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX, | ||
671 | attrs[TIPC_NLA_NAME_TABLE], NULL); | ||
672 | |||
673 | nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, nt[TIPC_NLA_NAME_TABLE_PUBL], | ||
674 | NULL); | ||
675 | |||
676 | ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req); | ||
677 | |||
678 | depth = ntohl(ntq->depth); | ||
679 | type = ntohl(ntq->type); | ||
680 | lowbound = ntohl(ntq->lowbound); | ||
681 | upbound = ntohl(ntq->upbound); | ||
682 | |||
683 | if (!(depth & TIPC_NTQ_ALLTYPES) && | ||
684 | (type != nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]))) | ||
685 | return 0; | ||
686 | if (lowbound && (lowbound > nla_get_u32(publ[TIPC_NLA_PUBL_UPPER]))) | ||
687 | return 0; | ||
688 | if (upbound && (upbound < nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]))) | ||
689 | return 0; | ||
690 | |||
691 | tipc_tlv_sprintf(msg->rep, "%-10u ", | ||
692 | nla_get_u32(publ[TIPC_NLA_PUBL_TYPE])); | ||
693 | |||
694 | if (depth == 1) | ||
695 | goto out; | ||
696 | |||
697 | tipc_tlv_sprintf(msg->rep, "%-10u %-10u ", | ||
698 | nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]), | ||
699 | nla_get_u32(publ[TIPC_NLA_PUBL_UPPER])); | ||
700 | |||
701 | if (depth == 2) | ||
702 | goto out; | ||
703 | |||
704 | node = nla_get_u32(publ[TIPC_NLA_PUBL_NODE]); | ||
705 | sprintf(port_str, "<%u.%u.%u:%u>", tipc_zone(node), tipc_cluster(node), | ||
706 | tipc_node(node), nla_get_u32(publ[TIPC_NLA_PUBL_REF])); | ||
707 | tipc_tlv_sprintf(msg->rep, "%-26s ", port_str); | ||
708 | |||
709 | if (depth == 3) | ||
710 | goto out; | ||
711 | |||
712 | tipc_tlv_sprintf(msg->rep, "%-10u %s", | ||
713 | nla_get_u32(publ[TIPC_NLA_PUBL_REF]), | ||
714 | scope_str[nla_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]); | ||
715 | out: | ||
716 | tipc_tlv_sprintf(msg->rep, "\n"); | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | |||
629 | static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) | 721 | static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) |
630 | { | 722 | { |
631 | struct tipc_nl_compat_cmd_dump dump; | 723 | struct tipc_nl_compat_cmd_dump dump; |
@@ -675,6 +767,14 @@ static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) | |||
675 | doit.doit = tipc_nl_link_reset_stats; | 767 | doit.doit = tipc_nl_link_reset_stats; |
676 | doit.transcode = tipc_nl_compat_link_reset_stats; | 768 | doit.transcode = tipc_nl_compat_link_reset_stats; |
677 | return tipc_nl_compat_doit(&doit, msg); | 769 | return tipc_nl_compat_doit(&doit, msg); |
770 | case TIPC_CMD_SHOW_NAME_TABLE: | ||
771 | msg->req_type = TIPC_TLV_NAME_TBL_QUERY; | ||
772 | msg->rep_size = ULTRA_STRING_MAX_LEN; | ||
773 | msg->rep_type = TIPC_TLV_ULTRA_STRING; | ||
774 | dump.header = tipc_nl_compat_name_table_dump_header; | ||
775 | dump.dumpit = tipc_nl_name_table_dump; | ||
776 | dump.format = tipc_nl_compat_name_table_dump; | ||
777 | return tipc_nl_compat_dumpit(&dump, msg); | ||
678 | } | 778 | } |
679 | 779 | ||
680 | return -EOPNOTSUPP; | 780 | return -EOPNOTSUPP; |
@@ -780,6 +880,7 @@ static int tipc_nl_compat_tmp_wrap(struct sk_buff *skb, struct genl_info *info) | |||
780 | case TIPC_CMD_SET_LINK_PRI: | 880 | case TIPC_CMD_SET_LINK_PRI: |
781 | case TIPC_CMD_SET_LINK_WINDOW: | 881 | case TIPC_CMD_SET_LINK_WINDOW: |
782 | case TIPC_CMD_RESET_LINK_STATS: | 882 | case TIPC_CMD_RESET_LINK_STATS: |
883 | case TIPC_CMD_SHOW_NAME_TABLE: | ||
783 | return tipc_nl_compat_recv(skb, info); | 884 | return tipc_nl_compat_recv(skb, info); |
784 | } | 885 | } |
785 | 886 | ||