2 * Routines for nstrace dissection
3 * Copyright 2006, Ravi Kondamuru <Ravi.Kondamuru@citrix.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <epan/packet.h>
30 #include <epan/wmem/wmem.h>
31 #include <wiretap/netscaler.h>
33 static int proto_nstrace
= -1;
35 static int hf_ns_nicno
= -1;
36 static int hf_ns_src_vm
= -1;
37 static int hf_ns_dst_vm
= -1;
38 static int hf_ns_dir
= -1;
39 static int hf_ns_pcbdevno
= -1;
40 static int hf_ns_l_pcbdevno
= -1;
41 static int hf_ns_devno
= -1;
42 static int hf_ns_vlantag
= -1;
43 static int hf_ns_coreid
= -1;
45 static int hf_ns_snode
= -1;
46 static int hf_ns_dnode
= -1;
47 static int hf_ns_clflags
= -1;
48 static int hf_ns_clflags_res
= -1;
49 static int hf_ns_clflags_rssh
= -1;
50 static int hf_ns_clflags_rss
= -1;
51 static int hf_ns_clflags_dfd
= -1;
52 static int hf_ns_clflags_fr
= -1;
53 static int hf_ns_clflags_fp
= -1;
55 static int hf_ns_activity
= -1;
56 static int hf_ns_activity_perf_collection
= -1;
57 static int hf_ns_activity_pcb_zombie
= -1;
58 static int hf_ns_activity_natpcb_zombie
= -1;
59 static int hf_ns_activity_lbstats_sync
= -1;
60 static int hf_ns_activity_stats_req
= -1;
63 static gint ett_ns
= -1;
64 static gint ett_ns_flags
= -1;
65 static gint ett_ns_activity_flags
= -1;
67 static const value_string ns_dir_vals
[] = {
68 { NSPR_PDPKTRACEFULLTX_V10
, "TX" },
69 { NSPR_PDPKTRACEFULLTX_V20
, "TX" },
70 { NSPR_PDPKTRACEFULLTXB_V10
, "TXB" },
71 { NSPR_PDPKTRACEFULLTXB_V20
, "TXB" },
72 { NSPR_PDPKTRACEFULLRX_V10
, "RX" },
73 { NSPR_PDPKTRACEFULLRX_V20
, "RX" },
74 { NSPR_PDPKTRACEPARTTX_V10
, "TX" },
75 { NSPR_PDPKTRACEPARTTX_V20
, "TX" },
76 { NSPR_PDPKTRACEPARTTXB_V10
, "TXB" },
77 { NSPR_PDPKTRACEPARTTXB_V20
, "TXB" },
78 { NSPR_PDPKTRACEPARTRX_V10
, "RX" },
79 { NSPR_PDPKTRACEPARTRX_V20
, "RX" },
80 { NSPR_PDPKTRACEFULLTX_V21
, "TX" },
81 { NSPR_PDPKTRACEFULLTXB_V21
, "TXB" },
82 { NSPR_PDPKTRACEFULLRX_V21
, "RX" },
83 { NSPR_PDPKTRACEPARTTX_V21
, "TX" },
84 { NSPR_PDPKTRACEPARTTXB_V21
, "TXB" },
85 { NSPR_PDPKTRACEPARTRX_V21
, "RX" },
86 { NSPR_PDPKTRACEFULLTX_V22
, "TX" },
87 { NSPR_PDPKTRACEFULLTX_V23
, "TX" },
88 { NSPR_PDPKTRACEFULLTX_V24
, "TX" },
89 { NSPR_PDPKTRACEFULLTX_V25
, "TX" },
90 { NSPR_PDPKTRACEFULLTX_V26
, "TX" },
91 { NSPR_PDPKTRACEFULLTXB_V22
, "TXB" },
92 { NSPR_PDPKTRACEFULLTXB_V23
, "TXB" },
93 { NSPR_PDPKTRACEFULLTXB_V24
, "TXB" },
94 { NSPR_PDPKTRACEFULLTXB_V25
, "TXB" },
95 { NSPR_PDPKTRACEFULLTXB_V26
, "TXB" },
96 { NSPR_PDPKTRACEFULLRX_V22
, "RX" },
97 { NSPR_PDPKTRACEFULLRX_V23
, "RX" },
98 { NSPR_PDPKTRACEFULLRX_V24
, "RX" },
99 { NSPR_PDPKTRACEFULLRX_V25
, "RX" },
100 { NSPR_PDPKTRACEFULLRX_V26
, "RX" },
101 { NSPR_PDPKTRACEFULLNEWRX_V24
, "NEW_RX" },
102 { NSPR_PDPKTRACEFULLNEWRX_V25
, "NEW_RX" },
103 { NSPR_PDPKTRACEFULLNEWRX_V26
, "NEW_RX" },
104 { NSPR_PDPKTRACEPARTTX_V22
, "TX" },
105 { NSPR_PDPKTRACEPARTTX_V23
, "TX" },
106 { NSPR_PDPKTRACEPARTTX_V24
, "TX" },
107 { NSPR_PDPKTRACEPARTTX_V25
, "TX" },
108 { NSPR_PDPKTRACEPARTTX_V26
, "TX" },
109 { NSPR_PDPKTRACEPARTTXB_V22
, "TXB" },
110 { NSPR_PDPKTRACEPARTTXB_V23
, "TXB" },
111 { NSPR_PDPKTRACEPARTTXB_V24
, "TXB" },
112 { NSPR_PDPKTRACEPARTTXB_V25
, "TXB" },
113 { NSPR_PDPKTRACEPARTTXB_V26
, "TXB" },
114 { NSPR_PDPKTRACEPARTRX_V22
, "RX" },
115 { NSPR_PDPKTRACEPARTRX_V23
, "RX" },
116 { NSPR_PDPKTRACEPARTRX_V24
, "RX" },
117 { NSPR_PDPKTRACEPARTRX_V25
, "RX" },
118 { NSPR_PDPKTRACEPARTRX_V26
, "RX" },
119 { NSPR_PDPKTRACEPARTNEWRX_V24
, "NEW_RX" },
120 { NSPR_PDPKTRACEPARTNEWRX_V25
, "NEW_RX" },
121 { NSPR_PDPKTRACEPARTNEWRX_V26
, "NEW_RX" },
125 static dissector_handle_t eth_withoutfcs_handle
;
134 #define NS_PE_STATE_PERF_COLLECTION_IN_PROG 0x00000001
135 #define NS_PE_STATE_PCB_ZOMBIE_IN_PROG 0x00000002
136 #define NS_PE_STATE_NATPCB_ZOMBIE_IN_PROG 0x00000004
137 #define NS_PE_STATE_LBSTATS_SYNC_IN_PROG 0x00000008
138 #define NS_PE_STATE_STATS_REQ_IN_PROG 0x00000010
141 dissect_nstrace(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
143 proto_tree
*ns_tree
= NULL
, *flagtree
= NULL
;
144 proto_item
*ti
= NULL
, *flagitem
= NULL
;
145 struct nstr_phdr
*pnstr
= &(pinfo
->pseudo_header
->nstr
);
146 tvbuff_t
*next_tvb_eth_client
;
149 wmem_strbuf_t
*flags_strbuf
= wmem_strbuf_new_label(wmem_packet_scope());
150 static const gchar
*flags
[] = {"FP", "FR", "DFD", "SRSS", "RSSH"};
151 gboolean first_flag
= TRUE
;
152 guint8 flagoffset
, flagval
;
153 guint8 src_vmname_len
= 0, dst_vmname_len
= 0;
154 guint8 variable_ns_len
= 0;
157 wmem_strbuf_append(flags_strbuf
, "None");
159 if (pnstr
->rec_type
== NSPR_HEADER_VERSION205
)
161 src_vmname_len
= tvb_get_guint8(tvb
,pnstr
->src_vmname_len_offset
);
162 dst_vmname_len
= tvb_get_guint8(tvb
,pnstr
->dst_vmname_len_offset
);
163 variable_ns_len
= src_vmname_len
+ dst_vmname_len
;
164 pnstr
->eth_offset
+= variable_ns_len
;
167 ti
= proto_tree_add_protocol_format(tree
, proto_nstrace
, tvb
, 0, pnstr
->eth_offset
, "NetScaler Packet Trace");
168 ns_tree
= proto_item_add_subtree(ti
, ett_ns
);
170 proto_tree_add_item(ns_tree
, hf_ns_dir
, tvb
, pnstr
->dir_offset
, pnstr
->dir_len
, ENC_LITTLE_ENDIAN
);
171 proto_tree_add_item(ns_tree
, hf_ns_nicno
, tvb
, pnstr
->nicno_offset
, pnstr
->nicno_len
, ENC_LITTLE_ENDIAN
);
173 switch (pnstr
->rec_type
)
175 case NSPR_HEADER_VERSION206
:
176 flagoffset
= pnstr
->ns_activity_offset
;
177 flagval32
= tvb_get_letohl(tvb
, flagoffset
);
178 flagitem
= proto_tree_add_uint_format(ns_tree
, hf_ns_activity
, tvb
, flagoffset
, 4, flagval32
,
179 "Activity Flags: 0x%04x", flagval32
);
180 flagtree
= proto_item_add_subtree(flagitem
, ett_ns_activity_flags
);
181 proto_tree_add_item(flagtree
, hf_ns_activity_perf_collection
, tvb
, flagoffset
, 4, ENC_LITTLE_ENDIAN
);
182 proto_tree_add_item(flagtree
, hf_ns_activity_pcb_zombie
, tvb
, flagoffset
, 4, ENC_LITTLE_ENDIAN
);
183 proto_tree_add_item(flagtree
, hf_ns_activity_natpcb_zombie
, tvb
, flagoffset
, 4, ENC_LITTLE_ENDIAN
);
184 proto_tree_add_item(flagtree
, hf_ns_activity_lbstats_sync
, tvb
, flagoffset
, 4, ENC_LITTLE_ENDIAN
);
185 proto_tree_add_item(flagtree
, hf_ns_activity_stats_req
, tvb
, flagoffset
, 4, ENC_LITTLE_ENDIAN
);
187 case NSPR_HEADER_VERSION205
:
190 proto_tree_add_item(ns_tree
,hf_ns_src_vm
,tvb
,pnstr
->data_offset
,src_vmname_len
,ENC_LITTLE_ENDIAN
);
194 proto_tree_add_item(ns_tree
,hf_ns_dst_vm
,tvb
,pnstr
->data_offset
+src_vmname_len
,dst_vmname_len
,ENC_LITTLE_ENDIAN
);
198 case NSPR_HEADER_VERSION204
:
200 flagoffset
= pnstr
->clflags_offset
;
201 flagval
= tvb_get_guint8(tvb
, flagoffset
);
203 for (i
= 0; i
< 5; i
++) {
205 if (flagval
& bpos
) {
207 wmem_strbuf_truncate(flags_strbuf
, 0);
209 wmem_strbuf_append_printf(flags_strbuf
, "%s%s", first_flag
? "" : ", ", flags
[i
]);
214 proto_tree_add_item(ns_tree
, hf_ns_snode
, tvb
, pnstr
->srcnodeid_offset
, 2, ENC_LITTLE_ENDIAN
);
215 proto_tree_add_item(ns_tree
, hf_ns_dnode
, tvb
, pnstr
->destnodeid_offset
, 2, ENC_LITTLE_ENDIAN
);
217 flagitem
= proto_tree_add_uint_format_value(ns_tree
, hf_ns_clflags
, tvb
, flagoffset
, 1, flagval
,
218 "0x%02x (%s)", flagval
, wmem_strbuf_get_str(flags_strbuf
));
219 flagtree
= proto_item_add_subtree(flagitem
, ett_ns_flags
);
221 proto_tree_add_boolean(flagtree
, hf_ns_clflags_res
, tvb
, flagoffset
, 1, flagval
);
222 proto_tree_add_boolean(flagtree
, hf_ns_clflags_rssh
, tvb
, flagoffset
, 1, flagval
);
223 proto_tree_add_boolean(flagtree
, hf_ns_clflags_rss
, tvb
, flagoffset
, 1, flagval
);
224 proto_tree_add_boolean(flagtree
, hf_ns_clflags_dfd
, tvb
, flagoffset
, 1, flagval
);
225 proto_tree_add_boolean(flagtree
, hf_ns_clflags_fr
, tvb
, flagoffset
, 1, flagval
);
226 proto_tree_add_boolean(flagtree
, hf_ns_clflags_fp
, tvb
, flagoffset
, 1, flagval
);
228 case NSPR_HEADER_VERSION203
:
229 proto_tree_add_item(ns_tree
, hf_ns_coreid
, tvb
, pnstr
->coreid_offset
, 2, ENC_LITTLE_ENDIAN
);
230 /* fall through to next case */
232 case NSPR_HEADER_VERSION202
:
233 col_add_fstr(pinfo
->cinfo
, COL_8021Q_VLAN_ID
, "%d", tvb_get_letohs(tvb
, pnstr
->vlantag_offset
));
234 proto_tree_add_item(ns_tree
, hf_ns_vlantag
, tvb
, pnstr
->vlantag_offset
, 2, ENC_LITTLE_ENDIAN
);
235 /* fall through to next case */
237 case NSPR_HEADER_VERSION201
:
238 proto_tree_add_item(ns_tree
, hf_ns_pcbdevno
, tvb
, pnstr
->pcb_offset
, 4, ENC_LITTLE_ENDIAN
);
239 ti
= proto_tree_add_item(ns_tree
, hf_ns_devno
, tvb
, pnstr
->pcb_offset
, 4, ENC_LITTLE_ENDIAN
);
240 PROTO_ITEM_SET_HIDDEN(ti
);
242 proto_tree_add_item(ns_tree
, hf_ns_l_pcbdevno
, tvb
, pnstr
->l_pcb_offset
, 4, ENC_LITTLE_ENDIAN
);
243 ti
= proto_tree_add_item(ns_tree
, hf_ns_devno
, tvb
, pnstr
->l_pcb_offset
, 4, ENC_LITTLE_ENDIAN
);
244 PROTO_ITEM_SET_HIDDEN(ti
);
252 /* Dissect as Ethernet */
253 offset
= pnstr
->eth_offset
;
254 next_tvb_eth_client
= tvb_new_subset_remaining(tvb
, offset
);
255 call_dissector(eth_withoutfcs_handle
, next_tvb_eth_client
, pinfo
, tree
);
259 proto_register_ns(void)
261 static hf_register_info hf
[] = {
264 { "Nic No", "nstrace.nicno",
265 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
270 { "Src Vm Name", "nstrace.src_vm",
271 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
276 { "Dst Vm Name", "nstrace.dst_vm",
277 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
282 { "Core Id", "nstrace.coreid",
283 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
288 { "Operation", "nstrace.dir",
289 FT_UINT8
, BASE_HEX
, VALS(ns_dir_vals
), 0x0,
294 { "PcbDevNo", "nstrace.pdevno",
295 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
300 { "Linked PcbDevNo", "nstrace.l_pdevno",
301 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
306 { "DevNo", "nstrace.devno",
307 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
312 { "Vlan", "nstrace.vlan",
313 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
318 { "Source Node", "nstrace.snode",
319 FT_INT16
, BASE_DEC
, NULL
, 0x0,
324 { "Destination Node", "nstrace.dnode",
325 FT_INT16
, BASE_DEC
, NULL
, 0x0,
330 { "Cluster Flags", "nstrace.flags",
331 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
335 { &hf_ns_clflags_res
,
336 { "Reserved", "nstrace.flags.res",
337 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), CL_RES
,
341 { &hf_ns_clflags_rssh
,
342 { "RSSHASH", "nstrace.flags.rssh",
343 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), CL_RSSH
,
347 { &hf_ns_clflags_rss
,
348 { "SRSS", "nstrace.flags.srss",
349 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), CL_RSS
,
353 { &hf_ns_clflags_dfd
,
354 { "DFD", "nstrace.flags.dfd",
355 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), CL_DFD
,
360 { "Flow receiver (FR)", "nstrace.flags.fr",
361 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), CL_FR
,
366 { "Flow processor (FP)", "nstrace.flags.fp",
367 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), CL_FP
,
372 { "NetScaler Activity", "nstrace.activity",
373 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
377 { &hf_ns_activity_perf_collection
,
378 { "Perf Collection", "nstrace.activity.perfcollection",
379 FT_BOOLEAN
, 32, NULL
, NS_PE_STATE_PERF_COLLECTION_IN_PROG
,
383 { &hf_ns_activity_pcb_zombie
,
384 { "PCB Zombie", "nstrace.activity.pcbzombie",
385 FT_BOOLEAN
, 32, NULL
, NS_PE_STATE_PCB_ZOMBIE_IN_PROG
,
389 { &hf_ns_activity_natpcb_zombie
,
390 { "NATPCB Zombie", "nstrace.activity.natpcbzombie",
391 FT_BOOLEAN
, 32, NULL
, NS_PE_STATE_NATPCB_ZOMBIE_IN_PROG
,
395 { &hf_ns_activity_lbstats_sync
,
396 { "LB Stats Sync", "nstrace.activity.lbstatssync",
397 FT_BOOLEAN
, 32, NULL
, NS_PE_STATE_LBSTATS_SYNC_IN_PROG
,
401 { &hf_ns_activity_stats_req
,
402 { "Stats Req", "nstrace.activity.statsreq",
403 FT_BOOLEAN
, 32, NULL
, NS_PE_STATE_STATS_REQ_IN_PROG
,
409 static gint
*ett
[] = {
412 &ett_ns_activity_flags
,
415 proto_nstrace
= proto_register_protocol("NetScaler Trace", "NS Trace", "ns");
416 proto_register_field_array(proto_nstrace
, hf
, array_length(hf
));
417 proto_register_subtree_array(ett
, array_length(ett
));
422 void proto_reg_handoff_ns(void)
424 dissector_handle_t nstrace_handle
;
426 eth_withoutfcs_handle
= find_dissector("eth_withoutfcs");
428 nstrace_handle
= create_dissector_handle(dissect_nstrace
, proto_nstrace
);
429 dissector_add_uint("wtap_encap", WTAP_ENCAP_NSTRACE_1_0
, nstrace_handle
);
430 dissector_add_uint("wtap_encap", WTAP_ENCAP_NSTRACE_2_0
, nstrace_handle
);