2 * Routines for SDH/SONET encapsulation dissection
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 - 2012 Gerald Combs
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/prefs.h>
31 #include "packet-erf.h"
35 #define EXT_HDR_TYPE_RAW_LINK 5
37 static int proto_sdh
= -1;
39 static gint ett_sdh
= -1;
41 static int hf_sdh_a1
= -1;
42 static int hf_sdh_a2
= -1;
43 static int hf_sdh_j0
= -1;
44 static int hf_sdh_b1
= -1;
45 static int hf_sdh_e1
= -1;
46 static int hf_sdh_f1
= -1;
47 static int hf_sdh_d1
= -1;
48 static int hf_sdh_d2
= -1;
49 static int hf_sdh_d3
= -1;
50 static int hf_sdh_au
= -1;
51 static int hf_sdh_b2
= -1;
52 static int hf_sdh_k1
= -1;
53 static int hf_sdh_k2
= -1;
54 static int hf_sdh_d4
= -1;
55 static int hf_sdh_d5
= -1;
56 static int hf_sdh_d6
= -1;
57 static int hf_sdh_d7
= -1;
58 static int hf_sdh_d8
= -1;
59 static int hf_sdh_d9
= -1;
60 static int hf_sdh_d10
= -1;
61 static int hf_sdh_d11
= -1;
62 static int hf_sdh_d12
= -1;
63 static int hf_sdh_s1
= -1;
64 static int hf_sdh_m1
= -1;
65 static int hf_sdh_e2
= -1;
66 static int hf_sdh_h1
= -1;
67 static int hf_sdh_h2
= -1;
68 static int hf_sdh_j1
= -1;
70 static gint sdh_data_rate
= 1;
72 static const enum_val_t data_rates
[] = {
73 {"Attempt to guess", "Attempt to guess", -1},
75 {"OC-12", "OC-12", 4},
76 {"OC-24", "OC-24", 8},
77 {"OC-48", "OC-48", 16},
81 const value_string sdh_s1_vals
[] = {
82 { 0, "Quality unknown" },
93 { 11, "SDH Equipment Source" },
97 { 15, "do not use for sync" },
102 get_sdh_level(tvbuff_t
*tvb
, packet_info
*pinfo
)
106 /*data rate has been set in the SDH options*/
107 if(sdh_data_rate
!= -1) return sdh_data_rate
;
109 /*ERF specifies data rate*/
110 hdr
= erf_get_ehdr(pinfo
, EXT_HDR_TYPE_RAW_LINK
, NULL
);
112 switch((*hdr
& 0xff00) >> 8){
119 default: /*drop through and try the next method*/
124 /*returns the multiplier for each data level*/
125 switch(tvb_reported_length(tvb
)){
130 case 19440: /*OC-24*/
132 case 38880: /*OC-48*/
141 dissect_sdh(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
143 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SDH");
144 col_clear(pinfo
->cinfo
,COL_INFO
);
147 proto_tree
*sdh_tree
;
148 proto_item
*sdh_item
;
150 int level
= get_sdh_level(tvb
, pinfo
);
157 sdh_item
= proto_tree_add_protocol_format(tree
, proto_sdh
, tvb
, 0, -1, "SDH");
158 sdh_tree
= proto_item_add_subtree(sdh_item
, ett_sdh
);
160 h1
= tvb_get_guint8(tvb
, 0*level
+(3*level
*COLUMNS
));
161 h2
= tvb_get_guint8(tvb
, 3*level
+(3*level
*COLUMNS
));
162 au
= (h2
| ((0x03 & h1
) << 8));
164 proto_tree_add_item(sdh_tree
, hf_sdh_a1
, tvb
, 0*level
, 3*level
, ENC_BIG_ENDIAN
);
165 proto_tree_add_item(sdh_tree
, hf_sdh_a2
, tvb
, 3*level
, 3*level
, ENC_BIG_ENDIAN
);
166 proto_tree_add_item(sdh_tree
, hf_sdh_j0
, tvb
, 6*level
, 1, ENC_BIG_ENDIAN
);
167 proto_tree_add_item(sdh_tree
, hf_sdh_b1
, tvb
, 0*level
+(1*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
168 proto_tree_add_item(sdh_tree
, hf_sdh_e1
, tvb
, 3*level
+(1*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
169 proto_tree_add_item(sdh_tree
, hf_sdh_f1
, tvb
, 6*level
+(1*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
170 proto_tree_add_item(sdh_tree
, hf_sdh_d1
, tvb
, 0*level
+(2*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
171 proto_tree_add_item(sdh_tree
, hf_sdh_d2
, tvb
, 3*level
+(2*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
172 proto_tree_add_item(sdh_tree
, hf_sdh_d3
, tvb
, 6*level
+(2*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
173 proto_tree_add_item(sdh_tree
, hf_sdh_h1
, tvb
, 0*level
+(3*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
174 proto_tree_add_item(sdh_tree
, hf_sdh_h2
, tvb
, 3*level
+(3*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
175 proto_tree_add_uint(sdh_tree
, hf_sdh_au
, tvb
, 0*level
+(3*level
*COLUMNS
), 3*level
+1, au
);
176 proto_tree_add_item(sdh_tree
, hf_sdh_b2
, tvb
, 0*level
+(4*level
*COLUMNS
), 3*level
, ENC_BIG_ENDIAN
);
177 proto_tree_add_item(sdh_tree
, hf_sdh_k1
, tvb
, 3*level
+(4*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
178 proto_tree_add_item(sdh_tree
, hf_sdh_k2
, tvb
, 6*level
+(4*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
179 proto_tree_add_item(sdh_tree
, hf_sdh_d4
, tvb
, 0*level
+(5*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
180 proto_tree_add_item(sdh_tree
, hf_sdh_d5
, tvb
, 3*level
+(5*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
181 proto_tree_add_item(sdh_tree
, hf_sdh_d6
, tvb
, 6*level
+(5*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
182 proto_tree_add_item(sdh_tree
, hf_sdh_d7
, tvb
, 0*level
+(6*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
183 proto_tree_add_item(sdh_tree
, hf_sdh_d8
, tvb
, 3*level
+(6*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
184 proto_tree_add_item(sdh_tree
, hf_sdh_d9
, tvb
, 6*level
+(6*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
185 proto_tree_add_item(sdh_tree
, hf_sdh_d10
, tvb
, 0*level
+(7*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
186 proto_tree_add_item(sdh_tree
, hf_sdh_d11
, tvb
, 3*level
+(7*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
187 proto_tree_add_item(sdh_tree
, hf_sdh_d12
, tvb
, 6*level
+(7*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
188 proto_tree_add_item(sdh_tree
, hf_sdh_s1
, tvb
, 0*level
+(8*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
189 proto_tree_add_item(sdh_tree
, hf_sdh_m1
, tvb
, 3*level
+2+(8*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
190 proto_tree_add_item(sdh_tree
, hf_sdh_e2
, tvb
, 6*level
+(8*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
192 /*XXX: POH that au points to may not be in the same frame. Also wrong on pointer justification*/
193 /*calculate start of SPE by wrapping AU pointer*/
194 auoffset
= (((9 + 3*COLUMNS
) /*start after H3*/ + au
*3 + 9*(au
/87) /*add extra SOH rows to offset*/) * level
) % (COLUMNS
*9*level
);
195 proto_tree_add_item(sdh_tree
, hf_sdh_j1
, tvb
, auoffset
, 1, ENC_BIG_ENDIAN
);
200 proto_register_sdh(void)
202 static hf_register_info hf
[] = {
204 { "A1", "sdh.a1", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
206 { "A2", "sdh.a2", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
208 { "J0", "sdh.j0", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
210 { "B1", "sdh.b1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
212 { "E1", "sdh.e1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
214 { "F1", "sdh.f1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
216 { "D1", "sdh.d1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
218 { "D2", "sdh.d2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
220 { "D3", "sdh.d3", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
222 { "AU", "sdh.au", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
224 { "B2", "sdh.b2", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
226 { "K1", "sdh.k1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
228 { "K2", "sdh.k2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
230 { "D4", "sdh.d4", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
232 { "D5", "sdh.d5", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
234 { "D6", "sdh.d6", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
236 { "D7", "sdh.d7", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
238 { "D8", "sdh.d8", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
240 { "D9", "sdh.d9", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
242 { "D10", "sdh.d10", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
244 { "D11", "sdh.d11", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
246 { "D12", "sdh.d12", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
248 { "S1", "sdh.s1", FT_UINT8
, BASE_HEX
, VALS(sdh_s1_vals
), 0x0, NULL
, HFILL
}},
250 { "M1", "sdh.m1", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
252 { "E2", "sdh.e2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
254 { "J1", "sdh.j1", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
256 { "H1", "sdh.h1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
258 { "H2", "sdh.h2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
261 static gint
*ett
[] = {
265 module_t
*sdh_module
;
268 proto_sdh
= proto_register_protocol("SDH/SONET Protocol", "SDH", "sdh");
269 proto_register_field_array(proto_sdh
, hf
, array_length(hf
));
270 proto_register_subtree_array(ett
, array_length(ett
));
272 sdh_module
= prefs_register_protocol(proto_sdh
, NULL
);
273 prefs_register_enum_preference(sdh_module
, "data.rate",
276 &sdh_data_rate
, data_rates
, ENC_BIG_ENDIAN
);
278 register_dissector("sdh", dissect_sdh
, proto_sdh
);
282 proto_reg_handoff_sdh(void)
284 dissector_handle_t sdh_handle
;
286 sdh_handle
= find_dissector("sdh");
287 dissector_add_uint("wtap_encap", WTAP_ENCAP_SDH
, sdh_handle
);