smb2-dissector: learn the "REPLAY_OPERATION" flag
[obnox/wireshark/wip.git] / epan / dissectors / packet-maccontrol.c
1 /* packet-maccontrol.c
2  * Routines for MAC Control ethernet header disassembly
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
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.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 /*
26  * 04/26/2010: WMeier: "Class-Based Flow Control [CBFC] Pause Frame"  dissection added
27  *             See: http://www.ieee802.org/1/files/public/docs2007/new-cm-barrass-pause-proposal.pdf
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include "packet-ieee8023.h"
37 #include "packet-llc.h"
38 #include <epan/etypes.h>
39
40 static int proto_macctrl = -1;
41
42 static int hf_macctrl_opcode       = -1;
43 static int hf_macctrl_pause_time   = -1;
44 static int hf_macctrl_cbfc_enbv    = -1;
45 static int hf_macctrl_cbfc_enbv_c0 = -1;
46 static int hf_macctrl_cbfc_enbv_c1 = -1;
47 static int hf_macctrl_cbfc_enbv_c2 = -1;
48 static int hf_macctrl_cbfc_enbv_c3 = -1;
49 static int hf_macctrl_cbfc_enbv_c4 = -1;
50 static int hf_macctrl_cbfc_enbv_c5 = -1;
51 static int hf_macctrl_cbfc_enbv_c6 = -1;
52 static int hf_macctrl_cbfc_enbv_c7 = -1;
53 static int hf_macctrl_cbfc_pause_time_c0 = -1;
54 static int hf_macctrl_cbfc_pause_time_c1 = -1;
55 static int hf_macctrl_cbfc_pause_time_c2 = -1;
56 static int hf_macctrl_cbfc_pause_time_c3 = -1;
57 static int hf_macctrl_cbfc_pause_time_c4 = -1;
58 static int hf_macctrl_cbfc_pause_time_c5 = -1;
59 static int hf_macctrl_cbfc_pause_time_c6 = -1;
60 static int hf_macctrl_cbfc_pause_time_c7 = -1;
61
62 static gint ett_macctrl            = -1;
63 static gint ett_macctrl_cbfc_enbv  = -1;
64 static gint ett_macctrl_cbfc_pause_times = -1;
65
66 static const int *macctrl_cbfc_enbv_list[] = {
67   &hf_macctrl_cbfc_enbv_c0,
68   &hf_macctrl_cbfc_enbv_c1,
69   &hf_macctrl_cbfc_enbv_c2,
70   &hf_macctrl_cbfc_enbv_c3,
71   &hf_macctrl_cbfc_enbv_c4,
72   &hf_macctrl_cbfc_enbv_c5,
73   &hf_macctrl_cbfc_enbv_c6,
74   &hf_macctrl_cbfc_enbv_c7,
75   NULL
76 };
77
78 static const int *macctrl_cbfc_pause_times_list[] = {
79   &hf_macctrl_cbfc_pause_time_c0,
80   &hf_macctrl_cbfc_pause_time_c1,
81   &hf_macctrl_cbfc_pause_time_c2,
82   &hf_macctrl_cbfc_pause_time_c3,
83   &hf_macctrl_cbfc_pause_time_c4,
84   &hf_macctrl_cbfc_pause_time_c5,
85   &hf_macctrl_cbfc_pause_time_c6,
86   &hf_macctrl_cbfc_pause_time_c7
87 };
88
89 #define MACCTRL_PAUSE                        0x0001
90 #define MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE 0x0101
91
92 static const value_string opcode_vals[] = {
93   { MACCTRL_PAUSE, "Pause" },
94   { MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE, "Class Based Flow Control [CBFC] Pause" },
95   { 0, NULL }
96 };
97
98 static void
99 dissect_macctrl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
100 {
101   proto_tree *ti;
102   proto_tree *macctrl_tree = NULL;
103   proto_tree *pause_times_tree = NULL;
104   guint16     opcode;
105   guint16     pause_time;
106
107   col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC CTRL");
108   col_clear(pinfo->cinfo, COL_INFO);
109
110   opcode = tvb_get_ntohs(tvb, 0);
111   if (tree) {
112     ti = proto_tree_add_item(tree, proto_macctrl, tvb, 0, 46, ENC_NA);
113     macctrl_tree = proto_item_add_subtree(ti, ett_macctrl);
114
115     proto_tree_add_uint(macctrl_tree, hf_macctrl_opcode, tvb, 0, 2, opcode);
116   }
117
118   switch (opcode) {
119
120     case MACCTRL_PAUSE:
121       pause_time = tvb_get_ntohs(tvb, 2);
122       col_add_fstr(pinfo->cinfo, COL_INFO, "MAC PAUSE: pause_time: %u quanta",
123                    pause_time);
124       if (tree)
125         proto_tree_add_uint(macctrl_tree, hf_macctrl_pause_time, tvb, 2, 2,
126                             pause_time);
127       break;
128
129     case MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE:
130       col_set_str(pinfo->cinfo, COL_INFO, "MAC CLASS BASED FLOW CONTROL PAUSE");
131       if (tree) {
132         int i;
133         proto_tree_add_bitmask(macctrl_tree, tvb, 2, hf_macctrl_cbfc_enbv,
134                                ett_macctrl_cbfc_enbv, macctrl_cbfc_enbv_list, ENC_BIG_ENDIAN);
135
136         ti = proto_tree_add_text(macctrl_tree, tvb, 4, 8*2, "CBFC Class Pause Times");
137         pause_times_tree = proto_item_add_subtree(ti, ett_macctrl_cbfc_pause_times);
138
139         for (i=0; i<8; i++) {
140           proto_tree_add_item(pause_times_tree, *macctrl_cbfc_pause_times_list[i], tvb, 4+i*2, 2, ENC_BIG_ENDIAN);
141         }
142       }
143       break;
144
145   }
146 }
147
148 void
149 proto_register_macctrl(void)
150 {
151   static hf_register_info hf[] = {
152     { &hf_macctrl_opcode,
153       { "Opcode", "macc.opcode", FT_UINT16, BASE_HEX,
154         VALS(opcode_vals), 0x0, "MAC Control opcode", HFILL}},
155
156     { &hf_macctrl_pause_time,
157       { "pause_time", "macc.pause_time", FT_UINT16, BASE_DEC,
158         NULL, 0x0, "MAC control PAUSE frame pause_time", HFILL }},
159
160     { &hf_macctrl_cbfc_enbv,
161       { "CBFC Class Enable Vector", "macc.cbfc.enbv", FT_UINT16, BASE_HEX,
162         NULL, 0x0, NULL, HFILL }},
163
164     { &hf_macctrl_cbfc_enbv_c0,
165       { "C0", "macc.cbfc.enbv.c0", FT_BOOLEAN, 16,
166         NULL, 0x01, NULL, HFILL }},
167
168     { &hf_macctrl_cbfc_enbv_c1,
169       { "C1", "macc.cbfc.enbv.c1", FT_BOOLEAN, 16,
170         NULL, 0x02, NULL, HFILL }},
171
172     { &hf_macctrl_cbfc_enbv_c2,
173       { "C2", "macc.cbfc.enbv.c2", FT_BOOLEAN, 16,
174         NULL, 0x04, NULL, HFILL }},
175
176     { &hf_macctrl_cbfc_enbv_c3,
177       { "C3", "macc.cbfc.enbv.c3", FT_BOOLEAN, 16,
178         NULL, 0x08, NULL, HFILL }},
179
180     { &hf_macctrl_cbfc_enbv_c4,
181       { "C4", "macc.cbfc.enbv.c4", FT_BOOLEAN, 16,
182         NULL, 0x10, NULL, HFILL }},
183
184     { &hf_macctrl_cbfc_enbv_c5,
185       { "C5", "macc.cbfc.enbv.c5", FT_BOOLEAN, 16,
186         NULL, 0x20, NULL, HFILL }},
187
188     { &hf_macctrl_cbfc_enbv_c6,
189       { "C6", "macc.cbfc.enbv.c6", FT_BOOLEAN, 16,
190         NULL, 0x40, NULL, HFILL }},
191
192     { &hf_macctrl_cbfc_enbv_c7,
193       { "C7", "macc.cbfc.enbv.c7", FT_BOOLEAN, 16,
194         NULL, 0x80, NULL, HFILL }},
195
196     { &hf_macctrl_cbfc_pause_time_c0,
197       { "C0", "macc.cbfc.pause_time.c0", FT_UINT16, BASE_DEC,
198         NULL, 0x00, NULL, HFILL }},
199
200     { &hf_macctrl_cbfc_pause_time_c1,
201       { "C1", "macc.cbfc.pause_time.c1", FT_UINT16, BASE_DEC,
202         NULL, 0x00, NULL, HFILL }},
203
204     { &hf_macctrl_cbfc_pause_time_c2,
205       { "C2", "macc.cbfc.pause_time.c2", FT_UINT16, BASE_DEC,
206         NULL, 0x00, NULL, HFILL }},
207
208     { &hf_macctrl_cbfc_pause_time_c3,
209       { "C3", "macc.cbfc.pause_time.c3", FT_UINT16, BASE_DEC,
210         NULL, 0x00, NULL, HFILL }},
211
212     { &hf_macctrl_cbfc_pause_time_c4,
213       { "C4", "macc.cbfc.pause_time.c4", FT_UINT16, BASE_DEC,
214         NULL, 0x00, NULL, HFILL }},
215
216     { &hf_macctrl_cbfc_pause_time_c5,
217       { "C5", "macc.cbfc.pause_time.c5", FT_UINT16, BASE_DEC,
218         NULL, 0x00, NULL, HFILL }},
219
220     { &hf_macctrl_cbfc_pause_time_c6,
221       { "C6", "macc.cbfc.pause_time.c6", FT_UINT16, BASE_DEC,
222         NULL, 0x00, NULL, HFILL }},
223
224     { &hf_macctrl_cbfc_pause_time_c7,
225       { "C7", "macc.cbfc.pause_time.c7", FT_UINT16, BASE_DEC,
226         NULL, 0x00, NULL, HFILL }}
227
228   };
229
230   static gint *ett[] = {
231         &ett_macctrl,
232         &ett_macctrl_cbfc_enbv,
233         &ett_macctrl_cbfc_pause_times
234   };
235   proto_macctrl = proto_register_protocol("MAC Control", "MACC", "macc");
236   proto_register_field_array(proto_macctrl, hf, array_length(hf));
237   proto_register_subtree_array(ett, array_length(ett));
238 }
239
240 void
241 proto_reg_handoff_macctrl(void)
242 {
243   dissector_handle_t macctrl_handle;
244
245   macctrl_handle = create_dissector_handle(dissect_macctrl, proto_macctrl);
246   dissector_add_uint("ethertype", ETHERTYPE_MAC_CONTROL, macctrl_handle);
247 }