aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2015-02-09 03:50:10 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-09 16:20:48 -0500
commit44a8ae94fd5525aa06a8c71cb52efbc418fb8b7c (patch)
tree7ccc0602ea66ed8b811a423fbcd0f7745127067d
parent1817877b3cd7b4dc73e4a1514d5f48eaa3989ec9 (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.c4
-rw-r--r--net/tipc/name_table.c184
-rw-r--r--net/tipc/name_table.h2
-rw-r--r--net/tipc/netlink_compat.c101
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 */
779static 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 */
818static 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 */
852static 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 */
875static 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
927struct 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
960int tipc_nametbl_init(struct net *net) 776int 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
98int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb); 98int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
99 99
100struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area,
101 int req_tlv_space);
102u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); 100u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node);
103int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, 101int 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
60struct tipc_nl_compat_cmd_dump { 61struct 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
634static 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
659static 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])]);
715out:
716 tipc_tlv_sprintf(msg->rep, "\n");
717
718 return 0;
719}
720
629static int tipc_nl_compat_handle(struct tipc_nl_compat_msg *msg) 721static 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