gem5  v20.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/cprintf.hh"
50 #include "base/logging.hh"
51 #include "base/types.hh"
52 
53 using namespace std;
54 namespace Net {
55 
56 EthAddr::EthAddr()
57 {
58  memset(data, 0, ETH_ADDR_LEN);
59 }
60 
61 EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
62 {
63  for (int i = 0; i < ETH_ADDR_LEN; ++i)
64  data[i] = ea[i];
65 }
66 
67 EthAddr::EthAddr(const eth_addr &ea)
68 {
69  for (int i = 0; i < ETH_ADDR_LEN; ++i)
70  data[i] = ea.data[i];
71 }
72 
73 EthAddr::EthAddr(const std::string &addr)
74 {
75  parse(addr);
76 }
77 
78 const EthAddr &
79 EthAddr::operator=(const eth_addr &ea)
80 {
81  *data = *ea.data;
82  return *this;
83 }
84 
85 const EthAddr &
86 EthAddr::operator=(const std::string &addr)
87 {
88  parse(addr);
89  return *this;
90 }
91 
92 void
93 EthAddr::parse(const std::string &addr)
94 {
95  // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
96  // the sscanf function won't work.
97  int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
98  if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
99  &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
100  memset(data, 0xff, ETH_ADDR_LEN);
101  return;
102  }
103 
104  for (int i = 0; i < ETH_ADDR_LEN; ++i) {
105  if (bytes[i] & ~0xff) {
106  memset(data, 0xff, ETH_ADDR_LEN);
107  return;
108  }
109 
110  data[i] = bytes[i];
111  }
112 }
113 
114 string
115 EthAddr::string() const
116 {
117  stringstream stream;
118  stream << *this;
119  return stream.str();
120 }
121 
122 bool
123 operator==(const EthAddr &left, const EthAddr &right)
124 {
125  return !memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
126 }
127 
128 ostream &
129 operator<<(ostream &stream, const EthAddr &ea)
130 {
131  const uint8_t *a = ea.addr();
132  ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
133  return stream;
134 }
135 
136 string
137 IpAddress::string() const
138 {
139  stringstream stream;
140  stream << *this;
141  return stream.str();
142 }
143 
144 bool
145 operator==(const IpAddress &left, const IpAddress &right)
146 {
147  return left.ip() == right.ip();
148 }
149 
150 ostream &
151 operator<<(ostream &stream, const IpAddress &ia)
152 {
153  uint32_t ip = ia.ip();
154  ccprintf(stream, "%x.%x.%x.%x",
155  (uint8_t)(ip >> 24), (uint8_t)(ip >> 16),
156  (uint8_t)(ip >> 8), (uint8_t)(ip >> 0));
157  return stream;
158 }
159 
160 string
161 IpNetmask::string() const
162 {
163  stringstream stream;
164  stream << *this;
165  return stream.str();
166 }
167 
168 bool
169 operator==(const IpNetmask &left, const IpNetmask &right)
170 {
171  return (left.ip() == right.ip()) &&
172  (left.netmask() == right.netmask());
173 }
174 
175 ostream &
176 operator<<(ostream &stream, const IpNetmask &in)
177 {
178  ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask());
179  return stream;
180 }
181 
182 string
183 IpWithPort::string() const
184 {
185  stringstream stream;
186  stream << *this;
187  return stream.str();
188 }
189 
190 bool
191 operator==(const IpWithPort &left, const IpWithPort &right)
192 {
193  return (left.ip() == right.ip()) && (left.port() == right.port());
194 }
195 
196 ostream &
197 operator<<(ostream &stream, const IpWithPort &iwp)
198 {
199  ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port());
200  return stream;
201 }
202 
203 uint16_t
204 cksum(const IpPtr &ptr)
205 {
206  int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
207  return ip_cksum_carry(sum);
208 }
209 
210 uint16_t
212 {
213  int tcplen = ip->len() - ip->hlen();
214  int sum = ip_cksum_add(ip->payload(), tcplen, 0);
215  sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
216  sum += htons(ip->ip_p + tcplen);
217  return ip_cksum_carry(sum);
218 }
219 
220 uint16_t
222 {
223  int tcplen = ip6->plen() - ip6->extensionLength();
224  int sum = ip_cksum_add(ip6->payload(), tcplen, 0);
225  sum = ip_cksum_add(ip6->src(), 32, sum);
226  sum += htons(ip6->proto() + tcplen);
227  return ip_cksum_carry(sum);
228 }
229 
230 uint16_t
231 cksum(const TcpPtr &tcp)
232 {
233  if (IpPtr(tcp.packet())) {
234  return __tu_cksum(IpPtr(tcp.packet()));
235  } else if (Ip6Ptr(tcp.packet())) {
236  return __tu_cksum6(Ip6Ptr(tcp.packet()));
237  } else {
238  panic("Unrecognized IP packet format");
239  }
240  // Should never reach here
241  return 0;
242 }
243 
244 uint16_t
245 cksum(const UdpPtr &udp)
246 {
247  if (IpPtr(udp.packet())) {
248  return __tu_cksum(IpPtr(udp.packet()));
249  } else if (Ip6Ptr(udp.packet())) {
250  return __tu_cksum6(Ip6Ptr(udp.packet()));
251  } else {
252  panic("Unrecognized IP packet format");
253  }
254  return 0;
255 }
256 
257 bool
258 IpHdr::options(vector<const IpOpt *> &vec) const
259 {
260  vec.clear();
261 
262  const uint8_t *data = bytes() + sizeof(struct ip_hdr);
263  int all = hlen() - sizeof(struct ip_hdr);
264  while (all > 0) {
265  const IpOpt *opt = (const IpOpt *)data;
266  int len = opt->len();
267  if (all < len)
268  return false;
269 
270  vec.push_back(opt);
271  all -= len;
272  data += len;
273  }
274 
275  return true;
276 }
277 
278 #define IP6_EXTENSION(nxt) (nxt == IP_PROTO_HOPOPTS) ? true : \
279  (nxt == IP_PROTO_ROUTING) ? true : \
280  (nxt == IP_PROTO_FRAGMENT) ? true : \
281  (nxt == IP_PROTO_AH) ? true : \
282  (nxt == IP_PROTO_ESP) ? true: \
283  (nxt == IP_PROTO_DSTOPTS) ? true : false
284 
285 /* Scan the IP6 header for all header extensions
286  * and return the number of headers found
287  */
288 int
289 Ip6Hdr::extensionLength() const
290 {
291  const uint8_t *data = bytes() + IP6_HDR_LEN;
292  uint8_t nxt = ip6_nxt;
293  int len = 0;
294  int all = plen();
295 
296  while (IP6_EXTENSION(nxt)) {
297  const Ip6Opt *ext = (const Ip6Opt *)data;
298  nxt = ext->nxt();
299  len += ext->len();
300  data += ext->len();
301  all -= ext->len();
302  assert(all >= 0);
303  }
304  return len;
305 }
306 
307 /* Scan the IP6 header for a particular extension
308  * header type and return a pointer to it if it
309  * exists, otherwise return NULL
310  */
311 const Ip6Opt*
312 Ip6Hdr::getExt(uint8_t ext_type) const
313 {
314  const uint8_t *data = bytes() + IP6_HDR_LEN;
315  uint8_t nxt = ip6_nxt;
316  Ip6Opt* opt = NULL;
317  int all = plen();
318 
319  while (IP6_EXTENSION(nxt)) {
320  opt = (Ip6Opt *)data;
321  if (nxt == ext_type) {
322  break;
323  }
324  nxt = opt->nxt();
325  data += opt->len();
326  all -= opt->len();
327  opt = NULL;
328  assert(all >= 0);
329  }
330  return (const Ip6Opt*)opt;
331 }
332 
333 /* Scan the IP6 header and any extension headers
334  * to find what type of Layer 4 header exists
335  * after this header
336  */
337 uint8_t
338 Ip6Hdr::proto() const
339 {
340  const uint8_t *data = bytes() + IP6_HDR_LEN;
341  uint8_t nxt = ip6_nxt;
342  int all = plen();
343 
344  while (IP6_EXTENSION(nxt)) {
345  const Ip6Opt *ext = (const Ip6Opt *)data;
346  nxt = ext->nxt();
347  data += ext->len();
348  all -= ext->len();
349  assert(all >= 0);
350  }
351  return nxt;
352 }
353 
354 bool
355 TcpHdr::options(vector<const TcpOpt *> &vec) const
356 {
357  vec.clear();
358 
359  const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
360  int all = off() - sizeof(struct tcp_hdr);
361  while (all > 0) {
362  const TcpOpt *opt = (const TcpOpt *)data;
363  int len = opt->len();
364  if (all < len)
365  return false;
366 
367  vec.push_back(opt);
368  all -= len;
369  data += len;
370  }
371 
372  return true;
373 }
374 
375 int
376 hsplit(const EthPacketPtr &ptr)
377 {
378  int split_point = 0;
379 
380  IpPtr ip(ptr);
381  Ip6Ptr ip6(ptr);
382  if (ip) {
383  split_point = ip.pstart();
384 
385  TcpPtr tcp(ip);
386  if (tcp)
387  split_point = tcp.pstart();
388 
389  UdpPtr udp(ip);
390  if (udp)
391  split_point = udp.pstart();
392  } else if (ip6) {
393  split_point = ip6.pstart();
394 
395  TcpPtr tcp(ip6);
396  if (tcp)
397  split_point = tcp.pstart();
398  UdpPtr udp(ip6);
399  if (udp)
400  split_point = udp.pstart();
401  }
402  return split_point;
403 }
404 
405 
406 } // namespace Net
Net::IpNetmask
Definition: inet.hh:266
data
const char data[]
Definition: circlebuf.test.cc:42
Net::EthAddr::bytes
const uint8_t * bytes() const
Definition: inet.hh:100
Net::IpHdr::bytes
const uint8_t * bytes() const
Definition: inet.hh:345
RiscvISA::sum
Bitfield< 18 > sum
Definition: registers.hh:609
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
Net::IpAddress
Definition: inet.hh:231
Net::EthAddr
Definition: inet.hh:72
Net::TcpPtr
Definition: inet.hh:637
iGbReg::TxdOp::tcp
bool tcp(TxDesc *d)
Definition: i8254xGBe_defs.hh:262
Net::UdpPtr
Definition: inet.hh:751
Net::IpAddress::ip
uint32_t ip() const
Definition: inet.hh:250
std::vector
STL vector class.
Definition: stl.hh:37
Net::IpHdr::hlen
uint8_t hlen() const
Definition: inet.hh:326
IP6_EXTENSION
#define IP6_EXTENSION(nxt)
Definition: inet.cc:278
Net::operator<<
ostream & operator<<(ostream &stream, const IpWithPort &iwp)
Definition: inet.cc:197
Net
Definition: inet.cc:54
Net::IpOpt::len
uint8_t len() const
Definition: inet.hh:428
Net::TcpOpt::len
uint8_t len() const
Definition: inet.hh:709
ArmISA::a
Bitfield< 8 > a
Definition: miscregs_types.hh:62
Net::IpPtr
Definition: inet.hh:351
MipsISA::ia
Bitfield< 18, 16 > ia
Definition: pra_constants.hh:234
Net::IpWithPort
Definition: inet.hh:294
Net::Ip6Opt::nxt
uint8_t nxt() const
Definition: inet.hh:585
Net::__tu_cksum6
uint16_t __tu_cksum6(const Ip6Ptr &ip6)
Definition: inet.cc:221
ArmISA::ext
Bitfield< 12 > ext
Definition: miscregs_types.hh:422
cprintf.hh
Net::IpWithPort::port
uint8_t port() const
Definition: inet.hh:309
Net::__tu_cksum
uint16_t __tu_cksum(const IpPtr &ip)
Definition: inet.cc:211
Net::operator==
bool operator==(const IpWithPort &left, const IpWithPort &right)
Definition: inet.cc:191
EthPacketPtr
std::shared_ptr< EthPacketData > EthPacketPtr
Definition: etherpkt.hh:87
Net::Ip6Opt
Definition: inet.hh:583
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
types.hh
Net::IpOpt
Definition: inet.hh:422
Net::Ip6Ptr
Definition: inet.hh:481
iGbReg::TxdOp::ip
bool ip(TxDesc *d)
Definition: i8254xGBe_defs.hh:261
ArmISA::len
Bitfield< 18, 16 > len
Definition: miscregs_types.hh:439
addr
ip6_addr_t addr
Definition: inet.hh:423
ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:127
logging.hh
ArmISA::ea
Bitfield< 3 > ea
Definition: miscregs_types.hh:325
Net::UdpPtr::packet
const EthPacketPtr packet() const
Definition: inet.hh:804
Net::hsplit
int hsplit(const EthPacketPtr &ptr)
Definition: inet.cc:376
inet.hh
MipsISA::ip6
Bitfield< 14 > ip6
Definition: pra_constants.hh:187
Net::TcpOpt
Definition: inet.hh:706
Net::IpNetmask::netmask
uint8_t netmask() const
Definition: inet.hh:281
Net::cksum
uint16_t cksum(const UdpPtr &udp)
Definition: inet.cc:245
Net::UdpPtr::pstart
int pstart() const
Definition: inet.hh:809
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
Net::Ip6Opt::len
uint8_t len() const
Definition: inet.hh:587

Generated on Wed Sep 30 2020 14:02:07 for gem5 by doxygen 1.8.17