EthernetFragmenter.cc
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 "EthernetFragmenter.hh"
15 
16 // Custom includes
17 
18 #define prefix_
19 
22 // senf::emu::EthernetFragmenter
23 
25  : fragmentationCount_(0)
26 {
27 }
28 
30 {
31  unsigned payloadSize (eth.size() - senf::EthernetPacketParser::fixed_bytes -
32  ((eth->type_length() == senf::EthVLanCPacketType::etherType) or (eth->type_length() == senf::EthVLanSPacketType::etherType)) * senf::EthVLanPacketParser::fixed_bytes);
33 
34  return payloadSize > threshold;
35 }
36 
38 {
39  unsigned tmp (fragmentationCount_);
40  fragmentationCount_ = 0;
41  return tmp;
42 }
43 
45 {
47  unsigned fragmentNr (1);
48  bool vlanCPresent (pkt->type_length() == senf::EthVLanCPacketType::etherType);
49  bool vlanSPresent (pkt->type_length() == senf::EthVLanSPacketType::etherType);
50  size_type payloadSize (pkt.size() - senf::EthernetPacketParser::fixed_bytes);
51  senf::PacketData::iterator payloadIter (std::next( pkt.data().begin(), senf::EthernetPacketParser::fixed_bytes +
52  ((vlanCPresent||vlanSPresent) * senf::EthVLanPacketParser::fixed_bytes)));
53  senf::PacketData::iterator payloadEnd (pkt.data().end());
54 
55  fragmentationCount_++;
56 
57  do {
58  senf::EthernetPacket eth (pkt.clone());
59  EthernetFragmentPacket fragmentHeader (EthernetFragmentPacket::createAfter(senf::EthOUIExtensionPacket::createAfter((vlanCPresent||vlanSPresent) ? eth.next() : eth) ));
60 
61  size_type fragmentPayloadSize (std::min( size_type(std::distance(payloadIter, payloadEnd)),
62  threshold - senf::EthOUIExtensionPacketParser::fixed_bytes - EthernetFragmentPacketParser::fixed_bytes));
63 
64  int fragmentSize (
65  senf::EthernetPacketParser::fixed_bytes +
66  ((vlanCPresent||vlanSPresent) * senf::EthVLanPacketParser::fixed_bytes) +
67  senf::EthOUIExtensionPacketParser::fixed_bytes +
68  EthernetFragmentPacketParser::fixed_bytes +
69  fragmentPayloadSize );
70 
71  size_type padding (std::max(0, int(senf::EthernetPacketType::minPayloadSize) - fragmentSize));
72 
73  senf::DataPacket fragmentPayload (senf::DataPacket::createAfter(fragmentHeader, fragmentPayloadSize+padding, senf::noinit));
74 
75  std::copy( payloadIter, std::next(payloadIter, fragmentPayloadSize), fragmentPayload.data().begin());
76  std::advance( payloadIter, fragmentPayloadSize);
77 
78  fragmentHeader->moreFragment() << (payloadIter != payloadEnd);
79  fragmentHeader->size() << (fragmentNr == 1 ? payloadSize : fragmentPayloadSize);
80  fragmentHeader->fragmentNr() << fragmentNr++;
81  if (vlanSPresent)
82  fragmentHeader->type_length() << pkt.next<senf::EthVLanSPacket>()->type_length();
83  else if (vlanCPresent)
84  fragmentHeader->type_length() << pkt.next<senf::EthVLanCPacket>()->type_length();
85  else
86  fragmentHeader->type_length() << pkt->type_length();
87 
88  eth.finalizeTo(fragmentHeader);
89 
90  v_outputFragment(eth);
91 
92  } while (payloadIter != payloadEnd);
93 }
94 
96 {
97 }
98 
99 prefix_ std::vector<senf::EthernetPacket> & senf::emu::EthernetFragmenter::fragments()
100 {
101  return fragments_;
102 }
103 
104 prefix_ void senf::emu::EthernetFragmenter::v_outputFragment(senf::EthernetPacket const & eth)
105 {
106  fragments_.emplace_back(eth);
107 }
108 
110 {
111  fragments_.clear();
112  do_fragmentFrame(eth, threshold);
113 }
114 
116  : defaultFragThresh_(std::max(std::uint16_t(576),defaultFragThresh))
117 {
118  route( input, output).autoThrottling(false);
119  bypass (false);
121 }
122 
124 {
125  if (!dst) {
126  if (threshold > 0)
127  defaultFragThresh_ = std::max(std::uint16_t(576), threshold);
128  fragThreshMap_.clear();
129  } else {
130  fragThreshMap_.erase(dst);
131  if (threshold > 0) {
132  fragThreshMap_.insert(std::make_pair(dst, std::max(std::uint16_t(576), threshold)));
133  }
134  }
135 }
136 
138  const
139 {
140  auto const it (fragThreshMap_.find(dst));
141  if (SENF_LIKELY(it != fragThreshMap_.end())) {
142  return it->second;
143  }
144 
145  return defaultFragThresh_;
146 }
147 
148 prefix_ boost::unordered_map<senf::MACAddress,std::uint16_t> const & senf::emu::EthernetFragmenterModule::fragThreshMap()
149  const
150 {
151  return fragThreshMap_;
152 }
153 
155 {
156  fragThreshMap_.clear();
157  bypass(false);
158 }
159 
161 {
162  input.onRequest( on ? &EthernetFragmenterModule::onRequestBypass : &EthernetFragmenterModule::onRequest);
163  bypass_ = on;
164 }
165 
167  const
168 {
169  return bypass_;
170 }
171 
172 prefix_ void senf::emu::EthernetFragmenterModule::v_outputFragment(senf::EthernetPacket const & eth)
173 {
174  output(eth);
175 }
176 
177 prefix_ void senf::emu::EthernetFragmenterModule::onRequest()
178 {
179  senf::EthernetPacket const & eth (input());
180  if (fragmentationRequired(eth, fragmentationThreshold(eth->destination())))
181  do_fragmentFrame(eth, fragmentationThreshold(eth->destination()));
182  else
183  output(eth);
184 }
185 
186 prefix_ void senf::emu::EthernetFragmenterModule::onRequestBypass()
187 {
188  output(input());
189 }
190 
191 
193 #undef prefix_
Route< connector::InputConnector, connector::OutputConnector > & route(connector::InputConnector &input, connector::OutputConnector &output)
static const unsigned minPayloadSize
senf::detail::packet::iterator iterator
ConcretePacket< EthVLanSPacketType > EthVLanSPacket
static const EtherTypes::key_t etherType
#define SENF_LIKELY(x)
STL namespace.
std::int32_t min
noinit
EthernetFragmenterModule(std::uint16_t defaultFragThresh=1500u)
std::int32_t max
static const EtherTypes::key_t etherType
void fragmentationThreshold(std::uint16_t _fragmentationThreshold, senf::MACAddress const &dst=senf::MACAddress::None)
boost::unordered_map< senf::MACAddress, std::uint16_t > const & fragThreshMap() const
std::vector< senf::EthernetPacket > & fragments()
senf::ppi::connector::PassiveInput< senf::EthernetPacket > input
raw_container::size_type size_type
senf::detail::packet::size_type size_type
senf::ppi::connector::ActiveOutput< senf::EthernetPacket > output
void fragmentFrame(senf::EthernetPacket const &pkt, unsigned treshold)
ConcretePacket< EthVLanCPacketType > EthVLanCPacket
void do_fragmentFrame(senf::EthernetPacket const &eth, unsigned threshold)
#define prefix_
ConcretePacket< EthernetPacketType > EthernetPacket
static ConcretePacket createAfter(Packet const &packet)
void throttlingDisc(ThrottlingDisc const &disc)
static bool fragmentationRequired(senf::EthernetPacket const &pkt, unsigned threshold)