21 #include <boost/date_time/posix_time/posix_time.hpp>
22 #include <boost/foreach.hpp>
35 using namespace boost::posix_time;
43 bool TestControl::interrupted_ =
false;
48 TestControl::hasLateExitCommenced()
const {
53 TestControl::waitToExit()
const {
54 static ptime exit_time = ptime(not_a_date_time);
59 if (wait_time && !haveAllPacketsBeenReceived()) {
60 const ptime now = microsec_clock::universal_time();
63 if (exit_time.is_not_a_date_time()) {
64 exit_time = now + time_duration(microseconds(wait_time));
68 return (now < exit_time);
76 TestControl::haveAllPacketsBeenReceived()
const {
80 const size_t& num_request_size = num_request.size();
82 if (num_request_size == 0) {
86 uint32_t responses = 0;
87 uint32_t requests = num_request[0];
88 if (num_request_size >= 2) {
89 requests += num_request[1];
93 responses = stats_mgr4_->getRcvdPacketsNum(StatsMgr4::XCHG_DO) +
94 stats_mgr4_->getRcvdPacketsNum(StatsMgr4::XCHG_RA);
96 responses = stats_mgr6_->getRcvdPacketsNum(StatsMgr6::XCHG_SA) +
97 stats_mgr6_->getRcvdPacketsNum(StatsMgr6::XCHG_RR);
100 return (responses == requests);
103 TestControl::TestControlSocket::TestControlSocket(
const int socket) :
105 ifindex_(0), valid_(true) {
114 IfacePtr iface = IfaceMgr::instance().getIface(ifindex_);
116 iface->delSocket(sockfd_);
121 TestControl::TestControlSocket::initSocketData() {
122 BOOST_FOREACH(
IfacePtr iface, IfaceMgr::instance().getIfaces()) {
123 BOOST_FOREACH(
SocketInfo s, iface->getSockets()) {
125 ifindex_ = iface->getIndex();
132 "descriptor not found");
138 return (test_control);
170 static boost::posix_time::ptime last_clean =
171 microsec_clock::universal_time();
174 time_period time_since_clean(last_clean,
175 microsec_clock::universal_time());
177 if (time_since_clean.length().total_seconds() >= 1) {
189 last_clean = microsec_clock::universal_time();
195 if (!pkt_from || !pkt_to) {
197 " for the copyIaOptions function");
205 " server's response");
207 pkt_to->addOption(option);
215 " server's response");
217 pkt_to->addOption(option);
225 const int b1 = b / 16;
226 const int b0 = b % 16;
227 ostringstream stream;
228 stream << std::hex << b1 << b0 << std::dec;
229 return (stream.str());
238 bool test_period_reached =
false;
243 if (period.length().total_seconds() >= options.
getPeriod()) {
244 test_period_reached =
true;
248 if (period.length().total_seconds() >= options.
getPeriod()) {
249 test_period_reached =
true;
253 if (test_period_reached) {
255 std::cout <<
"reached test-period." << std::endl;
262 bool max_requests =
false;
293 std::cout <<
"Reached max requests limit." << std::endl;
301 bool max_drops =
false;
331 std::cout <<
"Reached maximum drops number." << std::endl;
339 bool max_pdrops =
false;
378 std::cout <<
"Reached maximum percentage of drops." << std::endl;
391 " null DHCPACK message");
392 }
else if (ack->getYiaddr().isV4Zero()) {
394 " DHCPACK message containing yiaddr of 0");
397 msg->setCiaddr(ack->getYiaddr());
398 msg->setHWAddr(ack->getHWAddr());
409 <<
" to be created from Reply, expected DHCPV6_RENEW or"
414 const char* msg_type_str = (msg_type ==
DHCPV6_RENEW ?
"Renew" :
"Release");
418 <<
" message from the Reply message because the instance of"
419 " the Reply message is NULL");
427 <<
" message because client id option has not been found"
428 " in the Reply message");
430 msg->addOption(opt_clientid);
435 <<
" because server id option has not been found in the"
438 msg->addOption(opt_serverid);
446 if (buf.size() == 2) {
448 }
else if (buf.size() == 0) {
453 "elapsed time option buffer size has to be 0 or 2");
467 const uint8_t buf_array[] = {
469 0, 0, 3600 >> 8, 3600 & 0xff,
470 0, 0, 5400 >> 8, 5400 & 0xff,
472 OptionBuffer buf_ia_na(buf_array, buf_array +
sizeof(buf_array));
473 for (
size_t i = 0; i < buf.size(); ++i) {
474 buf_ia_na.push_back(buf[i]);
483 static const uint8_t buf_array[] = {
485 0, 0, 3600 >> 8, 3600 & 0xff,
486 0, 0, 5400 >> 8, 5400 & 0xff,
488 OptionBuffer buf_ia_pd(buf_array, buf_array +
sizeof(buf_array));
490 buf_ia_pd.insert(buf_ia_pd.end(), buf.begin(), buf.end());
505 const uint8_t buf_array[] = {
509 OptionBuffer buf_with_options(buf_array, buf_array +
sizeof(buf_array));
518 const uint8_t buf_array[] = {
528 OptionBuffer buf_with_options(buf_array, buf_array +
sizeof(buf_array));
530 opt->setData(buf_with_options.begin(), buf_with_options.end());
540 if (macs.size() > 0) {
542 if (r >= macs.size()) {
550 if (clients_num < 2) {
561 for (std::vector<uint8_t>::iterator it = mac_addr.end() - 1;
562 it >= mac_addr.begin();
584 std::vector<uint8_t> client_id(1,
static_cast<uint8_t
>(hwaddr->htype_));
585 client_id.insert(client_id.end(), hwaddr->hwaddr_.begin(),
586 hwaddr->hwaddr_.end());
597 if (macs.size() > 0) {
599 if (r >= macs.size()) {
602 std::vector<uint8_t> mac = macs[r];
616 uint8_t duid_ll[] = {0, 3, 0, 1, 0, 0, 0, 0, 0, 0};
618 std::vector<uint8_t> duid(duid_ll,
619 duid_ll +
sizeof(duid_ll) /
sizeof(duid_ll[0]));
621 std::copy(mac.begin(), mac.end(), duid.begin() + 4);
625 if ((clients_num == 0) || (clients_num == 1)) {
631 duid.resize(duid.size());
632 std::copy(mac_addr.begin(), mac_addr.end(),
633 duid.begin() + duid.size() - mac_addr.size());
641 ptime now(microsec_clock::universal_time());
665 return (time_period(now, due).length().total_microseconds());
671 DHCPV4_ELAPSED_TIME_OFFSET : DHCPV6_ELAPSED_TIME_OFFSET;
681 using namespace boost::posix_time;
682 ptime pkt1_time = pkt1->getTimestamp();
683 ptime pkt2_time = pkt2->getTimestamp();
684 if (pkt1_time.is_not_a_date_time() ||
685 pkt2_time.is_not_a_date_time()) {
688 time_period elapsed_period(pkt1_time, pkt2_time);
689 return (elapsed_period.is_null() ? 0 :
690 elapsed_period.length().total_milliseconds());
696 DHCPV4_RANDOMIZATION_OFFSET : DHCPV6_RANDOMIZATION_OFFSET;
700 return (rand_offset);
706 DHCPV4_REQUESTED_IP_OFFSET : DHCPV6_IA_NA_OFFSET;
716 if (ip_version == 4) {
717 return (
stats_mgr4_->getRcvdPacketsNum(xchg_type));
726 if (ip_version == 4) {
727 return (
stats_mgr4_->getSentPacketsNum(xchg_type));
736 DHCPV4_SERVERID_OFFSET : DHCPV6_SERVERID_OFFSET;
740 return (srvid_offset);
754 DHCPV4_TRANSID_OFFSET : DHCPV6_TRANSID_OFFSET;
764 while (wait3(&status, WNOHANG, NULL) > 0) {
781 for (std::vector<std::string>::const_iterator it = template_files.begin();
782 it != template_files.end(); ++it) {
793 const bool archive_mode =
testDiags(
't') ? true :
false;
825 stats_mgr4_->addCustomCounter(
"latesend",
"Late sent packets");
826 stats_mgr4_->addCustomCounter(
"shortwait",
"Short waits for packets");
827 stats_mgr4_->addCustomCounter(
"multircvd",
"Multiple packets receives");
828 stats_mgr4_->addCustomCounter(
"latercvd",
"Late received packets");
830 stats_mgr6_->addCustomCounter(
"latesend",
"Late sent packets");
831 stats_mgr6_->addCustomCounter(
"shortwait",
"Short waits for packets");
832 stats_mgr6_->addCustomCounter(
"multircvd",
"Multiple packets receives");
833 stats_mgr6_->addCustomCounter(
"latercvd",
"Late received packets");
846 uint8_t family = (options.
getIpVersion() == 6) ? AF_INET6 : AF_INET;
852 "Values for IP version: " <<
854 " and server address: " << servername <<
" are mismatched.");
858 if (family == AF_INET6) {
860 port = DHCP6_CLIENT_PORT;
863 port = DHCP6_SERVER_PORT;
872 if (!localname.empty()) {
877 sock = IfaceMgr::instance().openSocketFromIface(localname,
882 sock = IfaceMgr::instance().openSocketFromAddress(localaddr,
885 }
else if (!servername.empty()) {
888 sock = IfaceMgr::instance().openSocketFromRemoteAddress(remoteaddr,
900 int broadcast_enable = 1;
901 int ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
902 &broadcast_enable,
sizeof(broadcast_enable));
905 "unable to set broadcast option on the socket");
912 int ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
913 &hops,
sizeof(hops));
923 int idx = iface->getIndex();
924 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
929 "unable to enable multicast on socket " << sock
930 <<
". errno = " << errno);
940 const uint64_t packets_num,
941 const bool preload ) {
943 for (uint64_t i = packets_num; i > 0; --i) {
970 stats_mgr4_->incrementCounter(
"latercvd", latercvd);
972 stats_mgr6_->incrementCounter(
"latercvd", latercvd);
981 const uint64_t msg_num) {
982 for (uint64_t i = 0; i < msg_num; ++i) {
992 const uint32_t msg_type,
993 const uint64_t msg_num) {
994 for (uint64_t i = 0; i < msg_num; ++i) {
1019 std::string hex_buf;
1025 std::map<uint8_t, dhcp::Pkt4Ptr>::const_iterator pkt_it =
1030 const char* out_buf_data =
1031 static_cast<const char*
>(out_buf.
getData());
1032 std::vector<uint8_t> buf(out_buf_data, out_buf_data + out_buf.
getLength());
1039 std::map<uint8_t, dhcp::Pkt6Ptr>::const_iterator pkt_it =
1044 const char* out_buf_data =
1045 static_cast<const char*
>(out_buf.
getData());
1046 std::vector<uint8_t> buf(out_buf_data, out_buf_data + out_buf.
getLength());
1051 std::cout <<
"random-offset=" <<
getRandomOffset(arg_idx) << std::endl;
1058 std::cout <<
"contents: " << std::endl;
1061 while (line_len == 32) {
1062 if (hex_buf.length() - i < 32) {
1063 line_len = hex_buf.length() - i;
1066 std::cout << setfill(
'0') << setw(4) << std::hex << i << std::dec
1067 <<
" " << hex_buf.substr(i, line_len) << std::endl;
1071 std::cout << std::endl;
1090 std::string exchange_name =
"4-way exchanges";
1096 exchange_name =
"DISCOVER-OFFER";
1099 stats_mgr4_->getTestPeriod().length().total_nanoseconds() / 1e9;
1100 rate =
stats_mgr4_->getRcvdPacketsNum(xchg_type) / duration;
1107 "Solicit-Advertise";
1110 stats_mgr6_->getTestPeriod().length().total_nanoseconds() / 1e9;
1111 rate =
stats_mgr6_->getRcvdPacketsNum(xchg_type) / duration;
1113 std::ostringstream s;
1114 s <<
"***Rate statistics***" << std::endl;
1115 s <<
"Rate: " << rate <<
" " << exchange_name <<
"/second";
1117 s <<
", expected rate: " << options.
getRate() << std::endl;
1120 std::cout << s.str() << std::endl;
1127 ptime now = microsec_clock::universal_time();
1129 if (time_since_report.length().total_seconds() >= delay) {
1146 "hasn't been initialized");
1155 "hasn't been initialized");
1166 const std::string& separator )
const {
1167 std::ostringstream stream;
1168 for (std::vector<uint8_t>::const_iterator it = vec.begin();
1171 if (it == vec.begin()) {
1174 stream << separator <<
byte2Hex(*it);
1177 return (stream.str());
1182 std::ifstream temp_file;
1183 temp_file.open(file_name.c_str(), ios::in | ios::binary | ios::ate);
1184 if (!temp_file.is_open()) {
1188 std::streampos temp_size = temp_file.tellg();
1189 if (temp_size == std::streampos(0)) {
1193 temp_file.seekg(0, ios::beg);
1194 std::vector<char> file_contents(temp_size);
1195 temp_file.read(&file_contents[0], temp_size);
1201 std::vector<char> hex_digits;
1202 for (
size_t i = 0; i < file_contents.size(); ++i) {
1203 if (isxdigit(file_contents[i])) {
1204 hex_digits.push_back(file_contents[i]);
1205 }
else if (!isxdigit(file_contents[i]) &&
1206 !isspace(file_contents[i])) {
1208 " hexadecimal digit");
1212 if (hex_digits.size() % 2 != 0) {
1214 }
else if (hex_digits.empty()) {
1217 std::vector<uint8_t> binary_stream;
1218 for (
size_t i = 0; i < hex_digits.size(); i += 2) {
1220 s <<
"0x" << hex_digits[i] << hex_digits[i+1];
1223 binary_stream.push_back(
static_cast<uint8_t
>(b));
1245 }
else if (pkt4->getType() ==
DHCPACK) {
1274 uint8_t packet_type = pkt6->getType();
1329 bool receiving =
true;
1330 uint64_t received = 0;
1337 std::cerr <<
"Failed to receive DHCPv4 packet: "
1338 << e.
what() << std::endl;
1358 std::cerr <<
"Failed to receive DHCPv6 packet: "
1359 << e.
what() << std::endl;
1381 static bool factories_registered =
false;
1382 if (!factories_registered) {
1384 LibDHCP::OptionFactoryRegister(Option::V4,
1388 LibDHCP::OptionFactoryRegister(Option::V4,
1392 LibDHCP::OptionFactoryRegister(Option::V4,
1396 factories_registered =
true;
1401 static bool factories_registered =
false;
1402 if (!factories_registered) {
1404 LibDHCP::OptionFactoryRegister(Option::V6,
1408 LibDHCP::OptionFactoryRegister(Option::V6,
1412 LibDHCP::OptionFactoryRegister(Option::V6,
1416 LibDHCP::OptionFactoryRegister(Option::V6,
1420 LibDHCP::OptionFactoryRegister(Option::V6,
1424 LibDHCP::OptionFactoryRegister(Option::V6,
1429 LibDHCP::OptionFactoryRegister(Option::V6,
1435 factories_registered =
true;
1450 "before DHCP option factories can be registered");
1486 "command options must be parsed before running a test");
1489 IfaceMgr::instance().configureDHCPPacketQueue(AF_INET,
data::ElementPtr());
1493 IfaceMgr::instance().configureDHCPPacketQueue(AF_INET6,
data::ElementPtr());
1516 time_period duration(from_iso_string(
"20111231T235959"),
1517 microsec_clock::universal_time());
1518 srandom(duration.length().total_seconds()
1519 + duration.length().fractional_seconds());
1539 if ((packets_due == 0) &&
testDiags(
'i')) {
1566 uint64_t renew_packets_due =
1581 uint64_t release_packets_due =
1625 std::cout <<
"Interrupted" << std::endl;
1652 }
else if (pid == 0) {
1654 do_stop ?
"stop" :
"start",
1680 const bool preload ) {
1683 uint8_t randomized = 0;
1700 pkt4->addOption(Option::factory(Option::V4,
1708 pkt4->setHWAddr(
HTYPE_ETHER, mac_address.size(), mac_address);
1717 IfaceMgr::instance().send(pkt4);
1721 "hasn't been initialized");
1730 const std::vector<uint8_t>& template_buf,
1731 const bool preload ) {
1735 const uint8_t arg_idx = 0;
1737 uint8_t randomized = 0;
1750 std::vector<uint8_t> in_buf(template_buf.begin(),
1751 template_buf.end());
1761 pkt4->writeAt(rand_offset, mac_address.begin(), mac_address.end());
1763 setDefaults4(socket, boost::static_pointer_cast<Pkt4>(pkt4));
1767 IfaceMgr::instance().send(boost::static_pointer_cast<Pkt4>(pkt4));
1771 "hasn't been initialized");
1775 boost::static_pointer_cast<Pkt4>(pkt4));
1800 IfaceMgr::instance().send(msg);
1803 "hasn't been initialized");
1816 <<
" to be sent, expected DHCPV6_RENEW or DHCPV6_RELEASE");
1837 IfaceMgr::instance().send(msg);
1840 "hasn't been initialized");
1852 const uint32_t transid = discover_pkt4->getTransid();
1864 if (!opt_serverid) {
1866 <<
"in OFFER message");
1871 pkt4->addOption(opt_serverid);
1876 if (!yiaddr.
isV4()) {
1883 opt_requested_address->setUint32(yiaddr.
toUint32());
1884 pkt4->addOption(opt_requested_address);
1887 pkt4->addOption(opt_parameter_list);
1896 pkt4->setHWAddr(offer_pkt4->getHWAddr());
1900 uint32_t elapsed_time = getElapsedTime<Pkt4Ptr>(discover_pkt4, offer_pkt4);
1901 pkt4->setSecs(
static_cast<uint16_t
>(elapsed_time / 1000));
1904 IfaceMgr::instance().send(pkt4);
1907 "hasn't been initialized");
1915 const std::vector<uint8_t>& template_buf,
1920 const uint8_t arg_idx = 1;
1922 const uint32_t transid = discover_pkt4->getTransid();
1930 std::vector<uint8_t> in_buf(template_buf.begin(),
1931 template_buf.end());
1943 HWAddrPtr hwaddr = offer_pkt4->getHWAddr();
1945 uint8_t hw_len = hwaddr->hwaddr_.size();
1947 memcpy(&mac_address[0], &hwaddr->hwaddr_[0],
1950 pkt4->writeAt(rand_offset, mac_address.begin(), mac_address.end());
1954 uint32_t elapsed_time = getElapsedTime<Pkt4Ptr>(discover_pkt4, offer_pkt4);
1955 pkt4->writeValueAt<uint16_t>(elp_offset,
1956 static_cast<uint16_t
>(elapsed_time / 1000));
1964 boost::shared_ptr<LocalizedOption>
1969 pkt4->addOption(opt_serverid);
1975 if (!opt_serverid_offer) {
1977 <<
"in OFFER message");
1979 boost::shared_ptr<LocalizedOption>
1982 opt_serverid_offer->getData(),
1984 pkt4->addOption(opt_serverid);
1992 if (!yiaddr.
isV4()) {
2000 boost::shared_ptr<LocalizedOption>
2006 opt_requested_ip->setUint32(yiaddr.
toUint32());
2007 pkt4->addOption(opt_requested_ip);
2009 setDefaults4(socket, boost::static_pointer_cast<Pkt4>(pkt4));
2016 IfaceMgr::instance().send(boost::static_pointer_cast<Pkt4>(pkt4));
2019 "hasn't been initialized");
2023 boost::static_pointer_cast<Pkt4>(pkt4));
2029 const Pkt6Ptr& advertise_pkt6) {
2035 pkt6->addOption(opt_elapsed_time);
2038 if (!opt_clientid) {
2041 pkt6->addOption(opt_clientid);
2047 pkt6->addOption(Option::factory(Option::V6,
D6O_SERVERID,
2051 if (!opt_serverid) {
2057 pkt6->addOption(opt_serverid);
2075 IfaceMgr::instance().send(pkt6);
2078 "hasn't been initialized");
2086 const std::vector<uint8_t>& template_buf,
2087 const Pkt6Ptr& advertise_pkt6) {
2090 const uint8_t arg_idx = 1;
2096 transid_offset, transid));
2099 boost::shared_ptr<LocalizedOption>
2102 pkt6->addOption(opt_elapsed_time);
2110 boost::shared_ptr<LocalizedOption>
2115 pkt6->addOption(opt_serverid);
2122 if (!opt_serverid_advertise) {
2124 <<
"in ADVERTISE message");
2126 boost::shared_ptr<LocalizedOption>
2129 opt_serverid_advertise->getData(),
2131 pkt6->addOption(opt_serverid);
2137 boost::shared_ptr<Option6IA> opt_ia_na_advertise =
2138 boost::static_pointer_cast<Option6IA>(advertise_pkt6->getOption(
D6O_IA_NA));
2139 if (!opt_ia_na_advertise) {
2144 boost::shared_ptr<LocalizedOption>
2146 if (!opt_ia_na->valid()) {
2149 pkt6->addOption(opt_ia_na);
2152 if (!opt_serverid_advertise) {
2157 boost::shared_ptr<LocalizedOption>
2159 opt_serverid_advertise->getData(),
2161 pkt6->addOption(opt_serverid);
2165 if (!opt_clientid_advertise) {
2168 rand_offset -= (opt_clientid_advertise->len() - 1);
2170 boost::shared_ptr<LocalizedOption>
2172 opt_clientid_advertise->getData(),
2174 pkt6->addOption(opt_clientid);
2184 IfaceMgr::instance().send(pkt6);
2187 "hasn't been initialized");
2205 const bool preload ) {
2208 uint8_t randomized = 0;
2220 pkt6->addOption(Option::factory(Option::V6,
D6O_CLIENTID, duid));
2221 pkt6->addOption(Option::factory(Option::V6,
D6O_ORO));
2229 pkt6->addOption(Option::factory(Option::V6,
D6O_IA_NA));
2234 pkt6->addOption(Option::factory(Option::V6,
D6O_IA_PD));
2243 IfaceMgr::instance().send(pkt6);
2247 "hasn't been initialized");
2257 const std::vector<uint8_t>& template_buf,
2258 const bool preload ) {
2260 const int arg_idx = 0;
2267 transid_offset, transid));
2275 uint8_t randomized = 0;
2277 if (rand_offset > template_buf.size()) {
2281 pkt6->writeAt(rand_offset - randomized + 1,
2282 duid.end() - randomized, duid.end());
2292 IfaceMgr::instance().send(pkt6);
2296 "hasn't been initialized");
2311 if (iface == NULL) {
2314 pkt->setIface(iface->getName());
2318 pkt->setLocalPort(DHCP4_CLIENT_PORT);
2320 pkt->setRemotePort(DHCP4_SERVER_PORT);
2337 if (iface == NULL) {
2340 pkt->setIface(iface->getName());
2344 pkt->setLocalPort(DHCP6_CLIENT_PORT);
2346 pkt->setRemotePort(DHCP6_SERVER_PORT);
2348 pkt->setLocalAddr(socket.
addr_);
2361 pkt->addRelayInfo(relay_info);
2370 for (
auto entry : extra_opts) {
2371 pkt->addOption(entry.second);
2380 for (
auto entry : extra_opts) {
2381 pkt->addOption(entry.second);
2388 if (diags.find(diag) != std::string::npos) {