2 * Routines for MAC Control ethernet header disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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
33 #include <epan/packet.h>
34 #include "packet-llc.h"
35 #include <epan/etypes.h>
37 static int proto_macctrl
= -1;
39 static int hf_macctrl_opcode
= -1;
40 static int hf_macctrl_pause_time
= -1;
41 static int hf_macctrl_cbfc_enbv
= -1;
42 static int hf_macctrl_cbfc_enbv_c0
= -1;
43 static int hf_macctrl_cbfc_enbv_c1
= -1;
44 static int hf_macctrl_cbfc_enbv_c2
= -1;
45 static int hf_macctrl_cbfc_enbv_c3
= -1;
46 static int hf_macctrl_cbfc_enbv_c4
= -1;
47 static int hf_macctrl_cbfc_enbv_c5
= -1;
48 static int hf_macctrl_cbfc_enbv_c6
= -1;
49 static int hf_macctrl_cbfc_enbv_c7
= -1;
50 static int hf_macctrl_cbfc_pause_time_c0
= -1;
51 static int hf_macctrl_cbfc_pause_time_c1
= -1;
52 static int hf_macctrl_cbfc_pause_time_c2
= -1;
53 static int hf_macctrl_cbfc_pause_time_c3
= -1;
54 static int hf_macctrl_cbfc_pause_time_c4
= -1;
55 static int hf_macctrl_cbfc_pause_time_c5
= -1;
56 static int hf_macctrl_cbfc_pause_time_c6
= -1;
57 static int hf_macctrl_cbfc_pause_time_c7
= -1;
59 static gint ett_macctrl
= -1;
60 static gint ett_macctrl_cbfc_enbv
= -1;
61 static gint ett_macctrl_cbfc_pause_times
= -1;
63 static const int *macctrl_cbfc_enbv_list
[] = {
64 &hf_macctrl_cbfc_enbv_c0
,
65 &hf_macctrl_cbfc_enbv_c1
,
66 &hf_macctrl_cbfc_enbv_c2
,
67 &hf_macctrl_cbfc_enbv_c3
,
68 &hf_macctrl_cbfc_enbv_c4
,
69 &hf_macctrl_cbfc_enbv_c5
,
70 &hf_macctrl_cbfc_enbv_c6
,
71 &hf_macctrl_cbfc_enbv_c7
,
75 static const int *macctrl_cbfc_pause_times_list
[] = {
76 &hf_macctrl_cbfc_pause_time_c0
,
77 &hf_macctrl_cbfc_pause_time_c1
,
78 &hf_macctrl_cbfc_pause_time_c2
,
79 &hf_macctrl_cbfc_pause_time_c3
,
80 &hf_macctrl_cbfc_pause_time_c4
,
81 &hf_macctrl_cbfc_pause_time_c5
,
82 &hf_macctrl_cbfc_pause_time_c6
,
83 &hf_macctrl_cbfc_pause_time_c7
86 #define MACCTRL_PAUSE 0x0001
87 #define MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE 0x0101
89 static const value_string opcode_vals
[] = {
90 { MACCTRL_PAUSE
, "Pause" },
91 { MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE
, "Class Based Flow Control [CBFC] Pause" },
96 dissect_macctrl(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
99 proto_tree
*macctrl_tree
= NULL
;
100 proto_tree
*pause_times_tree
= NULL
;
104 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MAC CTRL");
105 col_clear(pinfo
->cinfo
, COL_INFO
);
107 opcode
= tvb_get_ntohs(tvb
, 0);
109 ti
= proto_tree_add_item(tree
, proto_macctrl
, tvb
, 0, 46, ENC_NA
);
110 macctrl_tree
= proto_item_add_subtree(ti
, ett_macctrl
);
112 proto_tree_add_uint(macctrl_tree
, hf_macctrl_opcode
, tvb
, 0, 2, opcode
);
118 pause_time
= tvb_get_ntohs(tvb
, 2);
119 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "MAC PAUSE: pause_time: %u quanta",
122 proto_tree_add_uint(macctrl_tree
, hf_macctrl_pause_time
, tvb
, 2, 2,
126 case MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE
:
127 col_set_str(pinfo
->cinfo
, COL_INFO
, "MAC CLASS BASED FLOW CONTROL PAUSE");
130 proto_tree_add_bitmask(macctrl_tree
, tvb
, 2, hf_macctrl_cbfc_enbv
,
131 ett_macctrl_cbfc_enbv
, macctrl_cbfc_enbv_list
, ENC_BIG_ENDIAN
);
133 ti
= proto_tree_add_text(macctrl_tree
, tvb
, 4, 8*2, "CBFC Class Pause Times");
134 pause_times_tree
= proto_item_add_subtree(ti
, ett_macctrl_cbfc_pause_times
);
136 for (i
=0; i
<8; i
++) {
137 proto_tree_add_item(pause_times_tree
, *macctrl_cbfc_pause_times_list
[i
], tvb
, 4+i
*2, 2, ENC_BIG_ENDIAN
);
146 proto_register_macctrl(void)
148 static hf_register_info hf
[] = {
149 { &hf_macctrl_opcode
,
150 { "Opcode", "macc.opcode", FT_UINT16
, BASE_HEX
,
151 VALS(opcode_vals
), 0x0, "MAC Control opcode", HFILL
}},
153 { &hf_macctrl_pause_time
,
154 { "pause_time", "macc.pause_time", FT_UINT16
, BASE_DEC
,
155 NULL
, 0x0, "MAC control PAUSE frame pause_time", HFILL
}},
157 { &hf_macctrl_cbfc_enbv
,
158 { "CBFC Class Enable Vector", "macc.cbfc.enbv", FT_UINT16
, BASE_HEX
,
159 NULL
, 0x0, NULL
, HFILL
}},
161 { &hf_macctrl_cbfc_enbv_c0
,
162 { "C0", "macc.cbfc.enbv.c0", FT_BOOLEAN
, 16,
163 NULL
, 0x01, NULL
, HFILL
}},
165 { &hf_macctrl_cbfc_enbv_c1
,
166 { "C1", "macc.cbfc.enbv.c1", FT_BOOLEAN
, 16,
167 NULL
, 0x02, NULL
, HFILL
}},
169 { &hf_macctrl_cbfc_enbv_c2
,
170 { "C2", "macc.cbfc.enbv.c2", FT_BOOLEAN
, 16,
171 NULL
, 0x04, NULL
, HFILL
}},
173 { &hf_macctrl_cbfc_enbv_c3
,
174 { "C3", "macc.cbfc.enbv.c3", FT_BOOLEAN
, 16,
175 NULL
, 0x08, NULL
, HFILL
}},
177 { &hf_macctrl_cbfc_enbv_c4
,
178 { "C4", "macc.cbfc.enbv.c4", FT_BOOLEAN
, 16,
179 NULL
, 0x10, NULL
, HFILL
}},
181 { &hf_macctrl_cbfc_enbv_c5
,
182 { "C5", "macc.cbfc.enbv.c5", FT_BOOLEAN
, 16,
183 NULL
, 0x20, NULL
, HFILL
}},
185 { &hf_macctrl_cbfc_enbv_c6
,
186 { "C6", "macc.cbfc.enbv.c6", FT_BOOLEAN
, 16,
187 NULL
, 0x40, NULL
, HFILL
}},
189 { &hf_macctrl_cbfc_enbv_c7
,
190 { "C7", "macc.cbfc.enbv.c7", FT_BOOLEAN
, 16,
191 NULL
, 0x80, NULL
, HFILL
}},
193 { &hf_macctrl_cbfc_pause_time_c0
,
194 { "C0", "macc.cbfc.pause_time.c0", FT_UINT16
, BASE_DEC
,
195 NULL
, 0x00, NULL
, HFILL
}},
197 { &hf_macctrl_cbfc_pause_time_c1
,
198 { "C1", "macc.cbfc.pause_time.c1", FT_UINT16
, BASE_DEC
,
199 NULL
, 0x00, NULL
, HFILL
}},
201 { &hf_macctrl_cbfc_pause_time_c2
,
202 { "C2", "macc.cbfc.pause_time.c2", FT_UINT16
, BASE_DEC
,
203 NULL
, 0x00, NULL
, HFILL
}},
205 { &hf_macctrl_cbfc_pause_time_c3
,
206 { "C3", "macc.cbfc.pause_time.c3", FT_UINT16
, BASE_DEC
,
207 NULL
, 0x00, NULL
, HFILL
}},
209 { &hf_macctrl_cbfc_pause_time_c4
,
210 { "C4", "macc.cbfc.pause_time.c4", FT_UINT16
, BASE_DEC
,
211 NULL
, 0x00, NULL
, HFILL
}},
213 { &hf_macctrl_cbfc_pause_time_c5
,
214 { "C5", "macc.cbfc.pause_time.c5", FT_UINT16
, BASE_DEC
,
215 NULL
, 0x00, NULL
, HFILL
}},
217 { &hf_macctrl_cbfc_pause_time_c6
,
218 { "C6", "macc.cbfc.pause_time.c6", FT_UINT16
, BASE_DEC
,
219 NULL
, 0x00, NULL
, HFILL
}},
221 { &hf_macctrl_cbfc_pause_time_c7
,
222 { "C7", "macc.cbfc.pause_time.c7", FT_UINT16
, BASE_DEC
,
223 NULL
, 0x00, NULL
, HFILL
}}
227 static gint
*ett
[] = {
229 &ett_macctrl_cbfc_enbv
,
230 &ett_macctrl_cbfc_pause_times
232 proto_macctrl
= proto_register_protocol("MAC Control", "MACC", "macc");
233 proto_register_field_array(proto_macctrl
, hf
, array_length(hf
));
234 proto_register_subtree_array(ett
, array_length(ett
));
238 proto_reg_handoff_macctrl(void)
240 dissector_handle_t macctrl_handle
;
242 macctrl_handle
= create_dissector_handle(dissect_macctrl
, proto_macctrl
);
243 dissector_add_uint("ethertype", ETHERTYPE_MAC_CONTROL
, macctrl_handle
);