VLanId.cci
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 #include <senf/Packets/DefaultBundle/EthernetPacket.hh>
15 
16 #define prefix_ inline
17 ///////////////////////////////cci.p////////////////////////////////////////
18 
19 
20 prefix_ bool senf::emu::VLanId::hasCTag(senf::EthernetPacket const & eth)
21 {
22 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
23  return *reinterpret_cast<std::uint16_t*>(&eth.data()[12]) == 0x0081u;
24 #else
25  return *reinterpret_cast<std::uint16_t*>(&eth.data()[12]) == 0x8100u;
26 #endif
27 }
28 
29 prefix_ bool senf::emu::VLanId::hasSTag(senf::EthernetPacket const & eth)
30 {
31 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
32  return *reinterpret_cast<std::uint16_t*>(&eth.data()[12]) == 0xa888u;
33 #else
34  return *reinterpret_cast<std::uint16_t*>(&eth.data()[12]) == 0x88a8u;
35 #endif
36 }
37 
38 prefix_ bool senf::emu::VLanId::hasTag(senf::EthernetPacket const & eth)
39 {
40  return hasCTag(eth) or hasSTag(eth);
41 }
42 
43 prefix_ std::uint16_t senf::emu::VLanId::payloadTypeLength(senf::EthernetPacket const & eth)
44 {
45  std::uint32_t offset (12); // first typeLength
46 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
47  while (((offset+2) <= eth.size()) and ((*reinterpret_cast<std::uint16_t*>(&eth.data()[offset]) == 0x0081u) or (*reinterpret_cast<std::uint16_t*>(&eth.data()[offset]) == 0xa888u)))
48  offset += 4;
49 #else
50  while (((offset+2) <= eth.size()) and ((*reinterpret_cast<std::uint16_t*>(&eth.data()[offset]) == 0x8100u) or (*reinterpret_cast<std::uint16_t*>(&eth.data()[offset]) == 0x88a8u)))
51  offset += 4;
52 #endif
53  if ((offset+2) <= eth.size())
54  return be16toh(*reinterpret_cast<std::uint16_t*>(&eth.data()[offset]));
55 
56  // inavlid TL after VLAN stack
57  return 0;
58 }
59 
60 template <class PKT>
61 prefix_ PKT senf::emu::VLanId::payload(senf::EthernetPacket const & eth)
62 {
63  senf::Packet pkt (eth.next(senf::nothrow));
64  while (pkt.is<senf::EthVLanCPacket>() or pkt.is<senf::EthVLanSPacket>()) {
65  pkt = pkt.next();
66  }
67 
68  if (SENF_LIKELY(pkt.is<PKT>()))
69  return pkt.as<PKT> ();
70 
71  return PKT ();
72 }
73 
74 prefix_ senf::Packet senf::emu::VLanId::payloadPkt(senf::EthernetPacket const & eth)
75 {
76  senf::Packet pkt (eth.next(senf::nothrow));
77  while (pkt.is<senf::EthVLanCPacket>() or pkt.is<senf::EthVLanSPacket>()) {
78  pkt = pkt.next();
79  }
80 
81  return pkt;
82 }
83 
84 // Fast path assumption is, we have a tag
85 prefix_ senf::emu::VLanId::VLanId(senf::EthernetPacket const & eth)
86 {
87  if (SENF_LIKELY(hasCTag(eth))) {
88  id_ = ((eth.data()[14] & 0xf) << 8) + eth.data()[15];
89  type_ = CTag;
90  }
91  else if (SENF_LIKELY(hasSTag(eth))) {
92  id_ = ((eth.data()[14] & 0xf) << 8) + eth.data()[15];
93  type_ = STag;
94  } else {
95  id_ = 0; // id == 0 is treated as untagged
96  type_ = NoTag;
97  }
98 }
99 
100 prefix_ std::uint16_t senf::emu::VLanId::id()
101  const
102 {
103  return id_;
104 }
105 
106 prefix_ senf::emu::VLanId::Type senf::emu::VLanId::type()
107  const
108 {
109  return Type(type_);
110 }
111 
112 prefix_ senf::emu::VLanId::operator bool()
113  const
114 {
115  return type_ != NoTag;
116 }
117 
118 prefix_ bool senf::emu::VLanId::stag()
119  const
120 {
121  return type_ == STag;
122 }
123 
124 prefix_ bool senf::emu::VLanId::ctag()
125  const
126 {
127  return type_ == CTag;
128 }
129 
130 prefix_ bool senf::emu::VLanId::sameTagType(VLanId const & other)
131  const
132 {
133  return type_ == other.type_;
134 }
135 
136 prefix_ bool senf::emu::VLanId::operator<(VLanId const & other)
137  const
138 {
139  // For now, do not differentiate between STag/CTag
140  return ((type_ == NoTag) < (other.type_ == NoTag)) or (((type_ == NoTag) == (other.type_ == NoTag)) and id_ < other.id_);
141 }
142 
143 prefix_ bool senf::emu::VLanId::operator==(VLanId const & other)
144  const
145 {
146  // For now, do not differentiate between STag/CTag
147  return id_ == other.id_ && ((type_ == NoTag) == (other.type_ == NoTag));
148 }
149 
150 prefix_ std::size_t std::hash<senf::emu::VLanId>::operator() (senf::emu::VLanId const & v)
151  const
152 {
153  hash<std::uint16_t> hasher;
154  // id() == 0 ane NoTag both map to 0 (untagged)
155  return hasher(v.id());
156 }
157 
158 prefix_ std::size_t senf::emu::hash_value(senf::emu::VLanId const & v)
159 {
160  boost::hash<std::uint16_t> hasher;
161  // id() == 0 ane NoTag both map to 0 (untagged)
162  return hasher(v.id());
163 }
164 
165 
166 ///////////////////////////////cci.e////////////////////////////////////////
167 #undef prefix_