gem5  v22.1.0.0
inet.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2002-2005 The Regents of The University of Michigan
15  * Copyright (c) 2010 Advanced Micro Devices, Inc.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41 
42 #include "base/inet.hh"
43 
44 #include <cstddef>
45 #include <cstdio>
46 #include <sstream>
47 #include <string>
48 
49 #include "base/compiler.hh"
50 #include "base/cprintf.hh"
51 #include "base/logging.hh"
52 #include "base/types.hh"
53 
54 namespace gem5
55 {
56 
57 GEM5_DEPRECATED_NAMESPACE(Net, networking);
58 namespace networking
59 {
60 
62 {
63  std::memset(data, 0, ETH_ADDR_LEN);
64 }
65 
66 EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
67 {
68  for (int i = 0; i < ETH_ADDR_LEN; ++i)
69  data[i] = ea[i];
70 }
71 
72 EthAddr::EthAddr(const eth_addr &ea)
73 {
74  for (int i = 0; i < ETH_ADDR_LEN; ++i)
75  data[i] = ea.data[i];
76 }
77 
78 EthAddr::EthAddr(const std::string &addr)
79 {
80  parse(addr);
81 }
82 
83 const EthAddr &
84 EthAddr::operator=(const eth_addr &ea)
85 {
86  *data = *ea.data;
87  return *this;
88 }
89 
90 const EthAddr &
91 EthAddr::operator=(const std::string &addr)
92 {
93  parse(addr);
94  return *this;
95 }
96 
97 void
98 EthAddr::parse(const std::string &addr)
99 {
100  // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
101  // the sscanf function won't work.
102  int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
103  if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
104  &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
105  std::memset(data, 0xff, ETH_ADDR_LEN);
106  return;
107  }
108 
109  for (int i = 0; i < ETH_ADDR_LEN; ++i) {
110  if (bytes[i] & ~0xff) {
111  std::memset(data, 0xff, ETH_ADDR_LEN);
112  return;
113  }
114 
115  data[i] = bytes[i];
116  }
117 }
118 
119 std::string
121 {
122  std::stringstream stream;
123  stream << *this;
124  return stream.str();
125 }
126 
127 bool
128 operator==(const EthAddr &left, const EthAddr &right)
129 {
130  return !std::memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
131 }
132 
133  std::ostream &
134 operator<<(std::ostream &stream, const EthAddr &ea)
135 {
136  const uint8_t *a = ea.addr();
137  ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
138  return stream;
139 }
140 
141 std::string
143 {
144  std::stringstream stream;
145  stream << *this;
146  return stream.str();
147 }
148 
149 bool
150 operator==(const IpAddress &left, const IpAddress &right)
151 {
152  return left.ip() == right.ip();
153 }
154 
155 std::ostream &
156 operator<<(std::ostream &stream, const IpAddress &ia)
157 {
158  uint32_t ip = ia.ip();
159  ccprintf(stream, "%x.%x.%x.%x",
160  (uint8_t)(ip >> 24), (uint8_t)(ip >> 16),
161  (uint8_t)(ip >> 8), (uint8_t)(ip >> 0));
162  return stream;
163 }
164 
165 std::string
167 {
168  std::stringstream stream;
169  stream << *this;
170  return stream.str();
171 }
172 
173 bool
174 operator==(const IpNetmask &left, const IpNetmask &right)
175 {
176  return (left.ip() == right.ip()) &&
177  (left.netmask() == right.netmask());
178 }
179 
180 std::ostream &
181 operator<<(std::ostream &stream, const IpNetmask &in)
182 {
183  ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask());
184  return stream;
185 }
186 
187 std::string
189 {
190  std::stringstream stream;
191  stream << *this;
192  return stream.str();
193 }
194 
195 bool
196 operator==(const IpWithPort &left, const IpWithPort &right)
197 {
198  return (left.ip() == right.ip()) && (left.port() == right.port());
199 }
200 
201 std::ostream &
202 operator<<(std::ostream &stream, const IpWithPort &iwp)
203 {
204  ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port());
205  return stream;
206 }
207 
208 uint16_t
209 cksum(const IpPtr &ptr)
210 {
211  int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
212  return ip_cksum_carry(sum);
213 }
214 
215 uint16_t
217 {
218  int tcplen = ip->len() - ip->hlen();
219  int sum = ip_cksum_add(ip->payload(), tcplen, 0);
220  sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
221  sum += htons(ip->ip_p + tcplen);
222  return ip_cksum_carry(sum);
223 }
224 
225 uint16_t
227 {
228  int tcplen = ip6->plen() - ip6->extensionLength();
229  int sum = ip_cksum_add(ip6->payload(), tcplen, 0);
230  sum = ip_cksum_add(ip6->src(), 32, sum);
231  sum += htons(ip6->proto() + tcplen);
232  return ip_cksum_carry(sum);
233 }
234 
235 uint16_t
236 cksum(const TcpPtr &tcp)
237 {
238  if (IpPtr(tcp.packet())) {
239  return __tu_cksum(IpPtr(tcp.packet()));
240  } else if (Ip6Ptr(tcp.packet())) {
241  return __tu_cksum6(Ip6Ptr(tcp.packet()));
242  } else {
243  panic("Unrecognized IP packet format");
244  }
245  // Should never reach here
246  return 0;
247 }
248 
249 uint16_t
250 cksum(const UdpPtr &udp)
251 {
252  if (IpPtr(udp.packet())) {
253  return __tu_cksum(IpPtr(udp.packet()));
254  } else if (Ip6Ptr(udp.packet())) {
255  return __tu_cksum6(Ip6Ptr(udp.packet()));
256  } else {
257  panic("Unrecognized IP packet format");
258  }
259  return 0;
260 }
261 
262 bool
264 {
265  vec.clear();
266 
267  const uint8_t *data = bytes() + sizeof(struct ip_hdr);
268  int all = hlen() - sizeof(struct ip_hdr);
269  while (all > 0) {
270  const IpOpt *opt = (const IpOpt *)data;
271  int len = opt->len();
272  if (all < len)
273  return false;
274 
275  vec.push_back(opt);
276  all -= len;
277  data += len;
278  }
279 
280  return true;
281 }
282 
283 namespace
284 {
285 
286 bool
287 ip6Extension(uint8_t nxt)
288 {
289  return nxt == IP_PROTO_HOPOPTS || nxt == IP_PROTO_ROUTING ||
290  nxt == IP_PROTO_FRAGMENT || nxt == IP_PROTO_AH ||
291  nxt == IP_PROTO_ESP || nxt == IP_PROTO_DSTOPTS;
292 }
293 
294 } // anonymous namespace
295 
296 /* Scan the IP6 header for all header extensions
297  * and return the number of headers found
298  */
299 int
301 {
302  const uint8_t *data = bytes() + IP6_HDR_LEN;
303  uint8_t nxt = ip6_nxt;
304  int len = 0;
305  GEM5_VAR_USED int all = plen();
306 
307  while (ip6Extension(nxt)) {
308  const Ip6Opt *ext = (const Ip6Opt *)data;
309  nxt = ext->nxt();
310  len += ext->len();
311  data += ext->len();
312  all -= ext->len();
313  assert(all >= 0);
314  }
315  return len;
316 }
317 
318 /* Scan the IP6 header for a particular extension
319  * header type and return a pointer to it if it
320  * exists, otherwise return NULL
321  */
322 const Ip6Opt*
323 Ip6Hdr::getExt(uint8_t ext_type) const
324 {
325  const uint8_t *data = bytes() + IP6_HDR_LEN;
326  uint8_t nxt = ip6_nxt;
327  Ip6Opt* opt = NULL;
328  GEM5_VAR_USED int all = plen();
329 
330  while (ip6Extension(nxt)) {
331  opt = (Ip6Opt *)data;
332  if (nxt == ext_type) {
333  break;
334  }
335  nxt = opt->nxt();
336  data += opt->len();
337  all -= opt->len();
338  opt = NULL;
339  assert(all >= 0);
340  }
341  return (const Ip6Opt*)opt;
342 }
343 
344 /* Scan the IP6 header and any extension headers
345  * to find what type of Layer 4 header exists
346  * after this header
347  */
348 uint8_t
350 {
351  const uint8_t *data = bytes() + IP6_HDR_LEN;
352  uint8_t nxt = ip6_nxt;
353  GEM5_VAR_USED int all = plen();
354 
355  while (ip6Extension(nxt)) {
356  const Ip6Opt *ext = (const Ip6Opt *)data;
357  nxt = ext->nxt();
358  data += ext->len();
359  all -= ext->len();
360  assert(all >= 0);
361  }
362  return nxt;
363 }
364 
365 bool
367 {
368  vec.clear();
369 
370  const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
371  int all = off() - sizeof(struct tcp_hdr);
372  while (all > 0) {
373  const TcpOpt *opt = (const TcpOpt *)data;
374  int len = opt->len();
375  if (all < len)
376  return false;
377 
378  vec.push_back(opt);
379  all -= len;
380  data += len;
381  }
382 
383  return true;
384 }
385 
386 int
387 hsplit(const EthPacketPtr &ptr)
388 {
389  int split_point = 0;
390 
391  IpPtr ip(ptr);
392  Ip6Ptr ip6(ptr);
393  if (ip) {
394  split_point = ip.pstart();
395 
396  TcpPtr tcp(ip);
397  if (tcp)
398  split_point = tcp.pstart();
399 
400  UdpPtr udp(ip);
401  if (udp)
402  split_point = udp.pstart();
403  } else if (ip6) {
404  split_point = ip6.pstart();
405 
406  TcpPtr tcp(ip6);
407  if (tcp)
408  split_point = tcp.pstart();
409  UdpPtr udp(ip6);
410  if (udp)
411  split_point = udp.pstart();
412  }
413  return split_point;
414 }
415 
416 } // namespace networking
417 } // namespace gem5
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
const char data[]
STL vector class.
Definition: stl.hh:37
#define GEM5_VAR_USED
Definition: compiler.hh:174
uint8_t netmask() const
Definition: inet.hh:287
int pstart() const
Definition: inet.hh:818
uint16_t cksum(const IpPtr &ptr)
Definition: inet.cc:209
uint16_t __tu_cksum6(const Ip6Ptr &ip6)
Definition: inet.cc:226
int hsplit(const EthPacketPtr &ptr)
Definition: inet.cc:387
const EthPacketPtr packet() const
Definition: inet.hh:813
uint16_t __tu_cksum(const IpPtr &ip)
Definition: inet.cc:216
uint8_t port() const
Definition: inet.hh:315
std::string string() const
Definition: inet.cc:142
bool operator==(const EthAddr &left, const EthAddr &right)
Definition: inet.cc:128
const uint8_t * addr() const
Definition: inet.hh:114
std::string string() const
Definition: inet.cc:120
std::ostream & operator<<(std::ostream &stream, const EthAddr &ea)
Definition: inet.cc:134
const EthAddr & operator=(const eth_addr &ea)
Definition: inet.cc:84
uint32_t ip() const
Definition: inet.hh:256
const uint8_t * bytes() const
Definition: inet.hh:106
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
uint16_t len
Definition: helpers.cc:62
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 3 > ea
Definition: misc_types.hh:335
Bitfield< 8 > a
Definition: misc_types.hh:66
Bitfield< 12 > ext
Definition: misc_types.hh:434
Bitfield< 14 > ip6
Bitfield< 18, 16 > ia
Bitfield< 25 > vec
Definition: misc.hh:113
Bitfield< 18 > sum
Definition: misc.hh:560
Bitfield< 3 > addr
Definition: types.hh:84
bool tcp(TxDesc *d)
bool ip(TxDesc *d)
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
std::shared_ptr< EthPacketData > EthPacketPtr
Definition: etherpkt.hh:90
void parse(const std::string &addr)
Definition: inet.cc:98
uint8_t nxt() const
Definition: inet.hh:463
uint16_t plen() const
Definition: inet.hh:461
const Ip6Opt * getExt(uint8_t ext) const
Definition: inet.cc:323
uint8_t proto() const
Definition: inet.cc:349
int extensionLength() const
Definition: inet.cc:300
const uint8_t * bytes() const
Definition: inet.hh:479
uint8_t nxt() const
Definition: inet.hh:594
uint8_t len() const
Definition: inet.hh:596
uint16_t len() const
Definition: inet.hh:334
uint8_t hlen() const
Definition: inet.hh:332
const uint8_t * bytes() const
Definition: inet.hh:351
bool options(std::vector< const IpOpt * > &vec) const
Definition: inet.cc:263
std::string string() const
Definition: inet.cc:166
uint8_t len() const
Definition: inet.hh:434
std::string string() const
Definition: inet.cc:188
const uint8_t * bytes() const
Definition: inet.hh:640
bool options(std::vector< const TcpOpt * > &vec) const
Definition: inet.cc:366
uint8_t off() const
Definition: inet.hh:627
uint8_t len() const
Definition: inet.hh:718

Generated on Wed Dec 21 2022 10:22:29 for gem5 by doxygen 1.9.1