-
Notifications
You must be signed in to change notification settings - Fork 3
/
L2.h
293 lines (211 loc) · 8.27 KB
/
L2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/*!
\file L2.h
\author Tom Mahler
\brief Declares the 2 class.
*/
#ifndef L2_H_
#define L2_H_
/*!
\def NETLAB_L2_DEBUG
Define in order to printout the L2 packets for debug
*/
//#define NETLAB_L2_DEBUG
#include "L3.h"
struct rtentry;
/*!
\class L2
\brief
Represents a Layer 2 interface (Ethernet).
\pre First initialize an instance of inet_os.
\pre Must define struct L2::ether_header.
*/
class L2 {
public:
/*!
\struct ether_header
\brief
Structure of a 10Mb/s Ethernet header. The Ethernet device driver is responsible for
converting ether_type between network and host byte order. Outside of the driver, it is
always in host byte order.
\note The Ethernet CRC is not generally available. It is computed and checked by the
interface hardware, which discards frames that arrive with an invalid CRC.
*/
struct ether_header;
/*!
\fn L2::L2(class inet_os &inet)
\brief Constructs an L2 interface.
\param [in,out] inet The inet.
*/
L2(class inet_os &inet);
/*!
\brief L2 destructor, updates its #inet that the interface is deleted.
*/
virtual ~L2();
/*!
\pure virtual void L2::ether_output(std::shared_ptr<std::vector<byte>> &m, std::vector<byte>::iterator &it, struct sockaddr *dst, struct L3::rtentry *rt) = 0;
\brief
We now examine the output of Ethernet frames, which starts when a network-level protocol
such as IP calls the \ref inet_os ether_output function, specified in the \ref inet_os
nic class. The output function for all Ethernet devices is ether_output (Figure 4.2).
ether_output takes the data portion of an Ethernet frame, encapsulates it with the 14-
byte Ethernet header, and places it on the interface's send queue. This is a large which
sums into four parts:
a. verification,
b. protocol-specific processing,
c. frame construction, and
d. interface queuing.
\param [in,out] m The std::shared_ptr<std::vector<byte>> to strip.
\param [in,out] it The iterator, as the current offset in the vector.
\param [in,out] dst the destination address of the packet.
\param [in,out] rt routing information.
*/
virtual void ether_output(std::shared_ptr<std::vector<byte>> &m, std::vector<byte>::iterator &it, struct sockaddr *dst, struct L3::rtentry *rt) = 0;
/*!
\pure virtual void L2::ether_input(std::shared_ptr<std::vector<byte>> &m, std::vector<byte>::iterator &it, struct ether_header *eh) = 0;
\brief
Process a received Ethernet packet. This method is called by the \ref NIC::leread(). It
unwraps the Ethernet header of the received data, drops invalid packets, passes the
unwraped data to the correct upper interface (i.e ARP and IP in our case) and possibly
prints relevant information.
\param [in,out] m The received data.
\param [in,out] it The iterator, as the current offset in the vector.
\param [in,out] eh pointer to a casted \ref ethernet_header
*/
virtual void ether_input(std::shared_ptr<std::vector<byte>> &m, std::vector<byte>::iterator &it, struct ether_header *eh) = 0;
protected:
class inet_os &inet; /*!< The inet_os owning this protocol. */
};
/************************************************************************/
/* SOLUTION */
/************************************************************************/
#include "HWAddress.hpp"
struct L2::ether_header
{
public:
/*!
\typedef netlab::HWAddress<> mac_addr
\brief Defines an alias representing the MAC address.
*/
typedef netlab::HWAddress<> mac_addr;
mac_addr ether_dhost; /*!< The Ethernet destination host */
mac_addr ether_shost; /*!< The Ethernet source host */
u_short ether_type; /*!< Type of the Ethernet \see ETHERTYPE_ */
/*!
\enum ETHERTYPE_
\brief
The Ethernet type for ::ether_type.
\note ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have (type-
ETHERTYPE_TRAIL)*512 bytes of data followed by an ETHER type (as given above) and then
the (variable-length) header.
*/
static enum ETHERTYPE_
{
ETHERTYPE_PUP = 0x0200, /*!< PUP protocol */
ETHERTYPE_IP = 0x0800, /*!< IP protocol */
ETHERTYPE_ARP = 0x0806, /*!< Address resolution protocol */
ETHERTYPE_REVARP = 0x8035, /*!< reverse Address resolution protocol */
ETHERTYPE_TRAIL = 0x1000, /*!< Trailer packet */
ETHERTYPE_NTRAILER = 16 /*!< The ETHERTYPE ntrailer option */
};
/*!
\enum ETH_
\brief Values that represent Ethernet header lengths.
*/
static enum ETH_
{
ETH_ALEN = 6, /*!< Octets in one Ethernet addr */
ETH_HLEN = 14, /*!< Total octets in header. */
ETH_ZLEN = 60, /*!< Min. octets in frame sans FCS */
ETH_DATA_LEN = 1500, /*!< Max. octets in payload */
ETH_FRAME_LEN = 1514, /*!< Max. octets in frame sans FCS */
ETH_FCS_LEN = 4 /*!< Octets in the FCS */
};
/*!
\enum ETHER_
\brief Values that represent Ethernet addresses lengths.
*/
static enum ETHER_
{
ETHER_ADDR_LEN = ETH_ALEN, /*!< size of Ethernet addr */
ETHER_TYPE_LEN = 2, /*!< bytes in type field */
ETHER_CRC_LEN = 4, /*!< bytes in CRC field */
ETHER_HDR_LEN = ETH_HLEN, /*!< total octets in header */
ETHER_MIN_LEN = (ETH_ZLEN + ETHER_CRC_LEN), /*!< min packet length */
ETHER_MAX_LEN = (ETH_FRAME_LEN + ETHER_CRC_LEN) /*!< max packet length */
};
/*!
\fn ether_header(const mac_addr shost, const mac_addr dhost, const ETHERTYPE_ type = ETHERTYPE_IP)
\brief Constructor.
\param shost The Ethernet source host
\param dhost The Ethernet destination host
\param type Type of the Ethernet \see ETHERTYPE_
*/
ether_header(const mac_addr shost, const mac_addr dhost, const ETHERTYPE_ type = ETHERTYPE_IP);
/*!
\fn ether_header(const ETHERTYPE_ type = ETHERTYPE_IP)
\brief Default constructor from \ref ETHERTYPE_.
\param type The type.
*/
ether_header(const ETHERTYPE_ type = ETHERTYPE_IP);
/*!
\fn friend std::ostream& operator<<(std::ostream &out, const L2::ether_header &eh)
\brief Stream insertion operator.
\param [in,out] out The output stream (usually std::cout).
\param eh The ether_header to printout.
\return The output stream, when #eh was inserted and printed.
*/
friend std::ostream& operator<<(std::ostream &out, const L2::ether_header &eh);
};
class L2_impl
: public L2
{
public:
/*!
\typedef netlab::HWAddress<> mac_addr
\brief Defines an alias representing the MAC address.
*/
typedef netlab::HWAddress<> mac_addr;
/*!
\enum L2_DEFAULT
\brief Global static default parameters.
*/
static enum L2_DEFAULT
{
ETHERMTU = L2::ether_header::ETH_DATA_LEN, /*!< The Ethernet MTU */
ETHERMIN = (L2::ether_header::ETHER_MIN_LEN - L2::ether_header::ETHER_HDR_LEN - L2::ether_header::ETHER_CRC_LEN), /*!< The Ethernet minimum size */
EHOSTDOWN = 64 /*!< The Ethernet Host is down */
};
/*!
\enum M_
\brief
Flags from the legacy mbuf struct, used for marking packet as #M_MCAST or #M_BCAST.
\note Unused.
*/
static enum M_
{
M_EXT = 0x0001, /*!< has associated external storage */
M_PKTHDR = 0x0002, /*!< start of record */
M_EOR = 0x0004, /*!< end of record */
M_BCAST = 0x0100, /*!< send/received as link-level broadcast */
M_MCAST = 0x0200 /*!< send/received as link-level multicast */
};
/* make sure Ethernet length is valid */
/*!
\fn template <typename T> static inline bool L2_impl::ETHER_IS_VALID_LEN(const T t)
\brief Ether is valid length.
\tparam T Generic type parameter.
\param t the size to check.
\return true if it succeeds, false if it fails.
*/
template <typename T>
static inline bool ETHER_IS_VALID_LEN(const T t) { return ((t >= static_cast<T>(ETHER_MIN_LEN)) && (t <= static_cast<T>(ETHER_MAX_LEN))); }
/*!
\fn L2_impl::L2_impl(class inet_os &inet)
\brief Constructor.
\param [in,out] inet The inet.
*/
L2_impl(class inet_os &inet);
virtual void ether_output(std::shared_ptr<std::vector<byte>> &m, std::vector<byte>::iterator &it, struct sockaddr *dst, struct L3::rtentry *rt);
virtual void ether_input(std::shared_ptr<std::vector<byte>> &m, std::vector<byte>::iterator &it, struct ether_header *eh);
};
#endif /* L2_H_ */