17 #include <boost/lexical_cast.hpp> 18 #include <boost/date_time/posix_time/posix_time.hpp> 41 CommandOptions::LeaseType::LeaseType()
51 return (lease_type == type_);
56 return (is(ADDRESS_AND_PREFIX) || (lease_type == type_));
66 if (cmd_line_arg ==
"address-only") {
69 }
else if (cmd_line_arg ==
"prefix-only") {
72 }
else if (cmd_line_arg ==
"address-and-prefix") {
73 type_ = ADDRESS_AND_PREFIX;
77 " must be one of the following: 'address-only' or" 86 return (
"address-only (IA_NA option added to the client's request)");
88 return (
"prefix-only (IA_PD option added to the client's request)");
89 case ADDRESS_AND_PREFIX:
90 return (
"address-and-prefix (Both IA_NA and IA_PD options added to the" 91 " client's request)");
94 " returning textual representation of the lease type");
108 uint8_t mac[6] = { 0x0, 0xC, 0x1, 0x2, 0x3, 0x4 };
112 double dt[2] = { 1., 1. };
124 mac_template_.assign(mac, mac + 6);
125 duid_template_.clear();
127 mac_list_file_.clear();
129 num_request_.clear();
133 drop_time_.assign(dt, dt + 2);
137 is_interface_ =
false;
144 rapid_commit_ =
false;
146 template_file_.clear();
154 server_name_.clear();
155 v6_relay_encapsulation_level_ = 0;
156 generateDuidTemplate();
199 bool help_or_version_mode = initialize(argc, argv, print_cmd_line);
200 if (!help_or_version_mode) {
203 return (help_or_version_mode);
207 CommandOptions::initialize(
int argc,
char** argv,
bool print_cmd_line) {
209 std::string drop_arg;
210 size_t percent_loc = 0;
211 double drop_percent = 0;
218 std::ostringstream stream;
219 stream <<
"perfdhcp";
220 int num_mac_list_files = 0;
224 while((opt = getopt(argc, argv,
"hv46A:r:t:R:b:n:p:d:D:l:P:a:L:M:" 225 "s:iBc1T:X:O:o:E:S:I:x:W:w:e:f:F:")) != -1) {
226 stream <<
" -" << static_cast<char>(opt);
228 stream <<
" " << optarg;
240 v6_relay_encapsulation_level_ =
241 static_cast<uint8_t>(positiveInteger(
"-A<encapsulation-level> must" 242 " be a positive integer"));
243 if (v6_relay_encapsulation_level_ != 1) {
249 check(ipversion_ == 6,
"IP version already set to 6");
254 check(ipversion_ == 4,
"IP version already set to 4");
259 aggressivity_ = positiveInteger(
"value of aggressivity: -a<value>" 260 " must be a positive integer");
264 check(base_.size() > 3,
"-b<value> already specified," 265 " unexpected occurrence of 5th -b<value>");
266 base_.push_back(optarg);
267 decodeBase(base_.back());
275 rapid_commit_ =
true;
279 check(drop_time_set_ > 1,
280 "maximum number of drops already specified, " 281 "unexpected 3rd occurrence of -d<value>");
283 drop_time_[drop_time_set_] =
284 boost::lexical_cast<double>(optarg);
285 }
catch (boost::bad_lexical_cast&) {
287 "value of drop time: -d<value>" 288 " must be positive number");
290 check(drop_time_[drop_time_set_] <= 0.,
291 "drop-time must be a positive number");
292 drop_time_set_ =
true;
296 drop_arg = std::string(optarg);
297 percent_loc = drop_arg.find(
'%');
298 check(max_pdrop_.size() > 1 || max_drop_.size() > 1,
299 "values of maximum drops: -D<value> already " 300 "specified, unexpected 3rd occurrence of -D<value>");
301 if ((percent_loc) != std::string::npos) {
304 boost::lexical_cast<double>(drop_arg.substr(0, percent_loc));
305 }
catch (boost::bad_lexical_cast&) {
307 "value of drop percentage: -D<value%>" 310 check((drop_percent <= 0) || (drop_percent >= 100),
311 "value of drop percentage: -D<value%> must be 0..100");
312 max_pdrop_.push_back(drop_percent);
314 num_drops = positiveInteger(
"value of max drops number:" 315 " -D<value> must be a positive integer");
316 max_drop_.push_back(num_drops);
325 elp_offset_ = nonNegativeInteger(
"value of time-offset: -E<value>" 326 " must not be a negative integer");
330 renew_rate_ = positiveInteger(
"value of the renew rate: -f<renew-rate>" 331 " must be a positive integer");
335 release_rate_ = positiveInteger(
"value of the release rate:" 336 " -F<release-rate> must be a" 337 " positive integer");
345 exchange_mode_ =
DO_SA;
349 rip_offset_ = positiveInteger(
"value of ip address offset:" 350 " -I<value> must be a" 351 " positive integer");
355 localname_ = std::string(optarg);
360 local_port_ = nonNegativeInteger(
"value of local port:" 361 " -L<value> must not be a" 362 " negative integer");
364 static_cast<int>(std::numeric_limits<uint16_t>::max()),
365 "local-port must be lower than " +
366 boost::lexical_cast<std::string>(std::numeric_limits<uint16_t>::max()));
370 check(num_mac_list_files >= 1,
"only -M option can be specified");
371 num_mac_list_files++;
372 mac_list_file_ = std::string(optarg);
377 exit_wait_time_ = nonNegativeInteger(
"value of exist wait time: " 378 "-W<value> must not be a " 383 num_req = positiveInteger(
"value of num-request:" 384 " -n<value> must be a positive integer");
385 if (num_request_.size() >= 2) {
387 "value of maximum number of requests: -n<value> " 388 "already specified, unexpected 3rd occurrence" 391 num_request_.push_back(num_req);
395 if (rnd_offset_.size() < 2) {
396 offset_arg = positiveInteger(
"value of random offset: " 397 "-O<value> must be greater than 3");
400 "random offsets already specified," 401 " unexpected 3rd occurrence of -O<value>");
403 check(offset_arg < 3,
"value of random random-offset:" 404 " -O<value> must be greater than 3 ");
405 rnd_offset_.push_back(offset_arg);
410 check( (ipversion_ != 4) && (ipversion_ != 6),
411 "-4 or -6 must be explicitly specified before -o is used.");
414 std::string opt_text = std::string(optarg);
415 size_t coma_loc = opt_text.find(
',');
416 check(coma_loc == std::string::npos,
417 "-o option must provide option code, a coma and hexstring for" 418 " the option content, e.g. -o60,646f63736973 for sending option" 419 " 60 (class-id) with the value 'docsis'");
424 code = boost::lexical_cast<int>(opt_text.substr(0,coma_loc));
425 check(code <= 0,
"Option code can't be negative");
426 }
catch (boost::bad_lexical_cast&) {
428 "-o option, expected format: -o<integer>,<hexstring>");
432 opt_text = opt_text.substr(coma_loc + 1);
433 std::vector<uint8_t> bin;
444 extra_opts_.insert(make_pair(code, opt));
448 period_ = positiveInteger(
"value of test period:" 449 " -p<value> must be a positive integer");
453 preload_ = nonNegativeInteger(
"number of preload packets:" 454 " -P<value> must not be " 455 "a negative integer");
459 rate_ = positiveInteger(
"value of rate:" 460 " -r<value> must be a positive integer");
468 seed_ = static_cast<unsigned int>
469 (nonNegativeInteger(
"value of seed:" 470 " -s <seed> must be non-negative integer"));
471 seeded_ = seed_ > 0 ? true :
false;
475 sid_offset_ = positiveInteger(
"value of server id offset:" 476 " -S<value> must be a" 477 " positive integer");
481 report_delay_ = positiveInteger(
"value of report delay:" 482 " -t<value> must be a" 483 " positive integer");
487 if (template_file_.size() < 2) {
488 sarg = nonEmptyString(
"template file name not specified," 489 " expected -T<filename>");
490 template_file_.push_back(sarg);
493 "template files are already specified," 494 " unexpected 3rd -T<filename> occurrence");
503 wrapped_ = nonEmptyString(
"command for wrapped mode:" 504 " -w<command> must be specified");
508 diags_ = nonEmptyString(
"value of diagnostics selectors:" 509 " -x<value> must be specified");
513 if (xid_offset_.size() < 2) {
514 offset_arg = positiveInteger(
"value of transaction id:" 515 " -X<value> must be a" 516 " positive integer");
519 "transaction ids already specified," 520 " unexpected 3rd -X<value> occurrence");
522 xid_offset_.push_back(offset_arg);
532 if (ipversion_ == 0) {
541 if (template_file_.size() > 1) {
542 if (xid_offset_.size() == 1) {
543 xid_offset_.push_back(xid_offset_[0]);
545 if (rnd_offset_.size() == 1) {
546 rnd_offset_.push_back(rnd_offset_[0]);
554 check(optind < argc -1,
"extra arguments?");
555 if (optind == argc - 1) {
556 server_name_ = argv[optind];
557 stream <<
" " << server_name_;
559 if ((ipversion_ == 4) && (server_name_.compare(
"all") == 0)) {
563 }
else if ((ipversion_ == 6) && (server_name_.compare(
"all") == 0)) {
565 }
else if ((ipversion_ == 6) &&
566 (server_name_.compare(
"servers") == 0)) {
571 if (print_cmd_line) {
572 std::cout <<
"Running: " << stream.str() << std::endl;
576 if (!localname_.empty()) {
577 if (server_name_.empty()) {
578 if (is_interface_ && (ipversion_ == 4)) {
581 }
else if (is_interface_ && (ipversion_ == 6)) {
586 if (server_name_.empty()) {
588 "without an interface, server is required");
593 if (duid_template_.empty()) {
594 generateDuidTemplate();
600 CommandOptions::initClientsNum() {
601 const std::string errmsg =
602 "value of -R <value> must be non-negative integer";
609 long long clients_num = boost::lexical_cast<long long>(optarg);
610 check(clients_num < 0, errmsg);
611 clients_num_ = boost::lexical_cast<uint32_t>(optarg);
612 }
catch (boost::bad_lexical_cast&) {
618 CommandOptions::initIsInterface() {
619 is_interface_ =
false;
620 if (!localname_.empty()) {
622 if (iface_mgr.
getIface(localname_) != NULL) {
623 is_interface_ =
true;
629 CommandOptions::decodeBase(
const std::string& base) {
631 boost::algorithm::to_lower(b);
634 if ((b.substr(0, 4) ==
"mac=") || (b.substr(0, 6) ==
"ether=")) {
636 }
else if (b.substr(0, 5) ==
"duid=") {
640 "base value not provided as -b<value>," 641 " expected -b mac=<mac> or -b duid=<duid>");
646 CommandOptions::decodeMacBase(
const std::string& base) {
648 size_t found = base.find(
'=');
649 static const char* errmsg =
"expected -b<base> format for" 650 " mac address is -b mac=00::0C::01::02::03::04 or" 651 " -b mac=00:0C:01:02:03:04";
652 check(found == std::string::npos, errmsg);
655 std::istringstream s1(base.substr(found + 1));
657 mac_template_.clear();
659 while (std::getline(s1, token,
':')) {
661 if (token.length() > 0) {
665 ui = convertHexString(token);
668 "invalid characters in MAC provided");
672 mac_template_.push_back(ui);
676 check(mac_template_.size() != 6, errmsg);
680 CommandOptions::decodeDuid(
const std::string& base) {
682 std::vector<uint8_t> duid_template;
683 size_t found = base.find(
'=');
684 check(found == std::string::npos,
"expected -b<base>" 685 " format for duid is -b duid=<duid>");
686 std::string b = base.substr(found + 1);
689 check(b.length() & 1,
"odd number of hexadecimal digits in duid");
690 check(b.length() > 128,
"duid too large");
691 check(b.length() == 0,
"no duid specified");
694 for (
size_t i = 0; i < b.length(); i += 2) {
698 ui = convertHexString(b.substr(i, 2));
701 "invalid characters in DUID provided," 702 " expected hex digits");
704 duid_template.push_back(static_cast<uint8_t>(ui));
709 check(duid_template.size() < 6,
"DUID must be at least 6 octets long");
711 std::swap(duid_template, duid_template_);
715 CommandOptions::generateDuidTemplate() {
716 using namespace boost::posix_time;
720 duid_template_.clear();
721 const uint8_t duid_template_len = 14;
722 duid_template_.resize(duid_template_len);
726 duid_template_[2] = HWTYPE_ETHERNET >> 8;
727 duid_template_[3] = HWTYPE_ETHERNET & 0xff;
732 ptime now = microsec_clock::universal_time();
733 ptime duid_epoch(from_iso_string(
"20000101T000000"));
734 time_period period(duid_epoch, now);
735 uint32_t duration_sec = htonl(period.length().total_seconds());
736 memcpy(&duid_template_[4], &duration_sec, 4);
741 memcpy(&duid_template_[8], &mac_template_[0], 6);
745 CommandOptions::convertHexString(
const std::string& text)
const {
748 for (
size_t i = 0; i < text.length(); ++i) {
749 if (!std::isxdigit(text[i])) {
751 "The following digit: " << text[i] <<
" in " 752 << text <<
"is not hexadecimal");
756 std::istringstream text_stream(text);
757 text_stream >> std::hex >> ui >> std::dec;
761 " two hex digits to byte");
766 void CommandOptions::loadMacs() {
768 std::ifstream infile(mac_list_file_.c_str());
770 while (std::getline(infile, line)) {
773 tmp <<
"invalid mac in input line " << cnt;
775 check(decodeMacString(line), tmp.str());
779 bool CommandOptions::decodeMacString(
const std::string& line) {
781 std::istringstream s(line);
783 std::vector<uint8_t> mac;
784 while(std::getline(s, token,
':')) {
786 if (token.length() > 0) {
790 ui = convertHexString(token);
798 mac_list_.push_back(mac);
803 CommandOptions::validate()
const {
805 "-B is not compatible with IPv6 (-6)");
807 "-6 (IPv6) must be set to use -c");
809 "Can't use -4 with -A, it's a V6 only option.");
811 "-F<release-rate> may be used with -6 (IPv6) only");
813 "second -n<num-request> is not compatible with -i");
815 "-6 option must be used if lease type other than '-e address-only'" 819 "template files may be only used with '-e address-only'");
821 "second -d<drop-time> is not compatible with -i");
824 "second -D<max-drop> is not compatible with -i");
826 "-1 is not compatible with -i");
828 "second -T<template-file> is not compatible with -i");
830 "second -X<xid-offset> is not compatible with -i");
832 "second -O<random-offset is not compatible with -i");
834 "-E<time-offset> is not compatible with -i");
836 "-S<srvid-offset> is not compatible with -i");
838 "-I<ip-offset> is not compatible with -i");
840 "-f<renew-rate> is not compatible with -i");
842 "-F<release-rate> is not compatible with -i");
844 "-i must be set to use -c");
846 "The sum of Renew rate (-f<renew-rate>) and Release rate" 847 " (-F<release-rate>) must not be greater than the exchange" 848 " rate specified as -r<rate>");
850 "Renew rate specified as -f<renew-rate> must not be specified" 851 " when -r<rate> parameter is not specified");
853 "Release rate specified as -F<release-rate> must not be specified" 854 " when -r<rate> parameter is not specified");
856 "-T<template-file> must be set to use -X<xid-offset>");
858 "-T<template-file> must be set to use -O<random-offset>");
860 "second/request -T<template-file> must be set to use -E<time-offset>");
862 "second/request -T<template-file> must be set to " 863 "use -S<srvid-offset>");
865 "second/request -T<template-file> must be set to " 866 "use -I<ip-offset>");
868 "Can't use -b with -M option");
872 CommandOptions::check(
bool condition,
const std::string& errmsg)
const {
875 std::ostringstream stream;
876 stream << errmsg <<
"\n";
883 CommandOptions::positiveInteger(
const std::string& errmsg)
const {
885 int value = boost::lexical_cast<int>(optarg);
886 check(value <= 0, errmsg);
888 }
catch (boost::bad_lexical_cast&) {
894 CommandOptions::nonNegativeInteger(
const std::string& errmsg)
const {
896 int value = boost::lexical_cast<int>(optarg);
897 check(value < 0, errmsg);
899 }
catch (boost::bad_lexical_cast&) {
905 CommandOptions::nonEmptyString(
const std::string& errmsg)
const {
906 std::string sarg = optarg;
907 if (sarg.length() == 0) {
914 CommandOptions::initLeaseType() {
915 std::string lease_type_arg = optarg;
921 std::cout <<
"IPv" << static_cast<int>(ipversion_) << std::endl;
922 if (exchange_mode_ ==
DO_SA) {
923 if (ipversion_ == 4) {
924 std::cout <<
"DISCOVER-OFFER only" << std::endl;
926 std::cout <<
"SOLICIT-ADVERTISE only" << std::endl;
931 std::cout <<
"rate[1/s]=" << rate_ << std::endl;
934 std::cout <<
"renew-rate[1/s]=" <<
getRenewRate() << std::endl;
937 std::cout <<
"release-rate[1/s]=" <<
getReleaseRate() << std::endl;
939 if (report_delay_ != 0) {
940 std::cout <<
"report[s]=" << report_delay_ << std::endl;
942 if (clients_num_ != 0) {
943 std::cout <<
"clients=" << clients_num_ << std::endl;
945 for (
size_t i = 0; i < base_.size(); ++i) {
946 std::cout <<
"base[" << i <<
"]=" << base_[i] << std::endl;
948 for (
size_t i = 0; i < num_request_.size(); ++i) {
949 std::cout <<
"num-request[" << i <<
"]=" << num_request_[i] << std::endl;
952 std::cout <<
"test-period=" << period_ << std::endl;
954 for (
size_t i = 0; i < drop_time_.size(); ++i) {
955 std::cout <<
"drop-time[" << i <<
"]=" << drop_time_[i] << std::endl;
957 for (
size_t i = 0; i < max_drop_.size(); ++i) {
958 std::cout <<
"max-drop{" << i <<
"]=" << max_drop_[i] << std::endl;
960 for (
size_t i = 0; i < max_pdrop_.size(); ++i) {
961 std::cout <<
"max-pdrop{" << i <<
"]=" << max_pdrop_[i] << std::endl;
964 std::cout <<
"preload=" << preload_ << std::endl;
966 std::cout <<
"aggressivity=" << aggressivity_ << std::endl;
968 std::cout <<
"local-port=" << local_port_ << std::endl;
971 std::cout <<
"seed=" << seed_ << std::endl;
974 std::cout <<
"broadcast" << std::endl;
977 std::cout <<
"rapid-commit" << std::endl;
980 std::cout <<
"use-first" << std::endl;
982 if (!mac_list_file_.empty()) {
983 std::cout <<
"mac-list-file=" << mac_list_file_ << std::endl;
985 for (
size_t i = 0; i < template_file_.size(); ++i) {
986 std::cout <<
"template-file[" << i <<
"]=" << template_file_[i] << std::endl;
988 for (
size_t i = 0; i < xid_offset_.size(); ++i) {
989 std::cout <<
"xid-offset[" << i <<
"]=" << xid_offset_[i] << std::endl;
991 if (elp_offset_ != 0) {
992 std::cout <<
"elp-offset=" << elp_offset_ << std::endl;
994 for (
size_t i = 0; i < rnd_offset_.size(); ++i) {
995 std::cout <<
"rnd-offset[" << i <<
"]=" << rnd_offset_[i] << std::endl;
997 if (sid_offset_ != 0) {
998 std::cout <<
"sid-offset=" << sid_offset_ << std::endl;
1000 if (rip_offset_ != 0) {
1001 std::cout <<
"rip-offset=" << rip_offset_ << std::endl;
1003 if (!diags_.empty()) {
1004 std::cout <<
"diagnostic-selectors=" << diags_ << std::endl;
1006 if (!wrapped_.empty()) {
1007 std::cout <<
"wrapped=" << wrapped_ << std::endl;
1009 if (!localname_.empty()) {
1010 if (is_interface_) {
1011 std::cout <<
"interface=" << localname_ << std::endl;
1013 std::cout <<
"local-addr=" << localname_ << std::endl;
1016 if (!server_name_.empty()) {
1017 std::cout <<
"server=" << server_name_ << std::endl;
1024 "perfdhcp [-hv] [-4|-6] [-A<encapsulation-level>] [-e<lease-type>]" 1025 " [-r<rate>] [-f<renew-rate>]\n" 1026 " [-F<release-rate>] [-t<report>] [-R<range>] [-b<base>]\n" 1027 " [-n<num-request>] [-p<test-period>] [-d<drop-time>]\n" 1028 " [-D<max-drop>] [-l<local-addr|interface>] [-P<preload>]\n" 1029 " [-a<aggressivity>] [-L<local-port>] [-s<seed>] [-i] [-B]\n" 1030 " [-W<late-exit-delay>]\n" 1031 " [-c] [-1] [-M<mac-list-file>] [-T<template-file>]\n" 1032 " [-X<xid-offset>] [-O<random-offset] [-E<time-offset>]\n" 1033 " [-S<srvid-offset>] [-I<ip-offset>] [-x<diagnostic-selector>]\n" 1034 " [-w<wrapped>] [server]\n" 1036 "The [server] argument is the name/address of the DHCP server to\n" 1037 "contact. For DHCPv4 operation, exchanges are initiated by\n" 1038 "transmitting a DHCP DISCOVER to this address.\n" 1040 "For DHCPv6 operation, exchanges are initiated by transmitting a DHCP\n" 1041 "SOLICIT to this address. In the DHCPv6 case, the special name 'all'\n" 1042 "can be used to refer to All_DHCP_Relay_Agents_and_Servers (the\n" 1043 "multicast address FF02::1:2), or the special name 'servers' to refer\n" 1044 "to All_DHCP_Servers (the multicast address FF05::1:3). The [server]\n" 1045 "argument is optional only in the case that -l is used to specify an\n" 1046 "interface, in which case [server] defaults to 'all'.\n" 1048 "The default is to perform a single 4-way exchange, effectively pinging\n" 1050 "The -r option is used to set up a performance test, without\n" 1051 "it exchanges are initiated as fast as possible.\n" 1054 "-1: Take the server-ID option from the first received message.\n" 1055 "-4: DHCPv4 operation (default). This is incompatible with the -6 option.\n" 1056 "-6: DHCPv6 operation. This is incompatible with the -4 option.\n" 1057 "-a<aggressivity>: When the target sending rate is not yet reached,\n" 1058 " control how many exchanges are initiated before the next pause.\n" 1059 "-b<base>: The base mac, duid, IP, etc, used to simulate different\n" 1060 " clients. This can be specified multiple times, each instance is\n" 1061 " in the <type>=<value> form, for instance:\n" 1062 " (and default) mac=00:0c:01:02:03:04.\n" 1063 "-d<drop-time>: Specify the time after which a request is treated as\n" 1064 " having been lost. The value is given in seconds and may contain a\n" 1065 " fractional component. The default is 1 second.\n" 1066 "-e<lease-type>: A type of lease being requested from the server. It\n" 1067 " may be one of the following: address-only, prefix-only or\n" 1068 " address-and-prefix. The address-only indicates that the regular\n" 1069 " address (v4 or v6) will be requested. The prefix-only indicates\n" 1070 " that the IPv6 prefix will be requested. The address-and-prefix\n" 1071 " indicates that both IPv6 address and prefix will be requested.\n" 1072 " The '-e prefix-only' and -'e address-and-prefix' must not be\n" 1074 "-E<time-offset>: Offset of the (DHCPv4) secs field / (DHCPv6)\n" 1075 " elapsed-time option in the (second/request) template.\n" 1076 " The value 0 disables it.\n" 1077 "-f<renew-rate>: Rate at which DHCPv4 or DHCPv6 renew requests are sent\n" 1078 " to a server. This value is only valid when used in conjunction\n" 1079 " with the exchange rate (given by -r<rate>). Furthermore the sum of\n" 1080 " this value and the release-rate (given by -F<rate) must be equal\n" 1081 " to or less than the exchange rate.\n" 1082 "-h: Print this help.\n" 1083 "-i: Do only the initial part of an exchange: DO or SA, depending on\n" 1084 " whether -6 is given.\n" 1085 "-I<ip-offset>: Offset of the (DHCPv4) IP address in the requested-IP\n" 1086 " option / (DHCPv6) IA_NA option in the (second/request) template.\n" 1087 "-l<local-addr|interface>: For DHCPv4 operation, specify the local\n" 1088 " hostname/address to use when communicating with the server. By\n" 1089 " default, the interface address through which traffic would\n" 1090 " normally be routed to the server is used.\n" 1091 " For DHCPv6 operation, specify the name of the network interface\n" 1092 " via which exchanges are initiated.\n" 1093 "-L<local-port>: Specify the local port to use\n" 1094 " (the value 0 means to use the default).\n" 1095 "-M<mac-list-file>: A text file containing a list of MAC addresses,\n" 1096 " one per line. If provided, a MAC address will be chosen randomly\n" 1097 " from this list for every new exchange. In the DHCPv6 case, MAC\n" 1098 " addresses are used to generate DUID-LLs. This parameter must not be\n" 1099 " used in conjunction with the -b parameter.\n" 1100 "-O<random-offset>: Offset of the last octet to randomize in the template.\n" 1101 "-P<preload>: Initiate first <preload> exchanges back to back at startup.\n" 1102 "-r<rate>: Initiate <rate> DORA/SARR (or if -i is given, DO/SA)\n" 1103 " exchanges per second. A periodic report is generated showing the\n" 1104 " number of exchanges which were not completed, as well as the\n" 1105 " average response latency. The program continues until\n" 1106 " interrupted, at which point a final report is generated.\n" 1107 "-R<range>: Specify how many different clients are used. With 1\n" 1108 " (the default), all requests seem to come from the same client.\n" 1109 "-s<seed>: Specify the seed for randomization, making it repeatable.\n" 1110 "-S<srvid-offset>: Offset of the server-ID option in the\n" 1111 " (second/request) template.\n" 1112 "-T<template-file>: The name of a file containing the template to use\n" 1113 " as a stream of hexadecimal digits.\n" 1114 "-v: Report the version number of this program.\n" 1115 "-W<time>: Specifies exit-wait-time parameter, that makes perfdhcp wait\n" 1116 " for <time> us after an exit condition has been met to receive all\n" 1117 " packets without sending any new packets. Expressed in microseconds.\n" 1118 "-w<wrapped>: Command to call with start/stop at the beginning/end of\n" 1120 "-x<diagnostic-selector>: Include extended diagnostics in the output.\n" 1121 " <diagnostic-selector> is a string of single-keywords specifying\n" 1122 " the operations for which verbose output is desired. The selector\n" 1123 " keyletters are:\n" 1124 " * 'a': print the decoded command line arguments\n" 1125 " * 'e': print the exit reason\n" 1126 " * 'i': print rate processing details\n" 1127 " * 's': print first server-id\n" 1128 " * 't': when finished, print timers of all successful exchanges\n" 1129 " * 'T': when finished, print templates\n" 1130 "-X<xid-offset>: Transaction ID (aka. xid) offset in the template.\n" 1132 "DHCPv4 only options:\n" 1133 "-B: Force broadcast handling.\n" 1135 "DHCPv6 only options:\n" 1136 "-c: Add a rapid commit option (exchanges will be SA).\n" 1137 "-F<release-rate>: Rate at which IPv6 Release requests are sent to\n" 1138 " a server. This value is only valid when used in conjunction with\n" 1139 " the exchange rate (given by -r<rate>). Furthermore the sum of\n" 1140 " this value and the renew-rate (given by -f<rate) must be equal\n" 1141 " to or less than the exchange rate.\n" 1142 "-A<encapsulation-level>: Specifies that relayed traffic must be\n" 1143 " generated. The argument specifies the level of encapsulation, i.e.\n" 1144 " how many relay agents are simulated. Currently the only supported\n" 1145 " <encapsulation-level> value is 1, which means that the generated\n" 1146 " traffic is an equivalent of the traffic passing through a single\n" 1149 "The remaining options are typically used in conjunction with -r:\n" 1151 "-D<max-drop>: Abort the test immediately if max-drop requests have\n" 1152 " been dropped. max-drop must be a positive integer. If max-drop\n" 1153 " includes the suffix '%', it specifies a maximum percentage of\n" 1154 " requests that may be dropped before abort. In this case, testing\n" 1155 " of the threshold begins after 10 requests have been expected to\n" 1157 "-n<num-request>: Initiate <num-request> transactions. No report is\n" 1158 " generated until all transactions have been initiated/waited-for,\n" 1159 " after which a report is generated and the program terminates.\n" 1160 "-p<test-period>: Send requests for the given test period, which is\n" 1161 " specified in the same manner as -d. This can be used as an\n" 1162 " alternative to -n, or both options can be given, in which case the\n" 1163 " testing is completed when either limit is reached.\n" 1164 "-t<report>: Delay in seconds between two periodic reports.\n" 1167 "- tooshort: received a too short message\n" 1168 "- orphans: received a message which doesn't match an exchange\n" 1169 " (duplicate, late or not related)\n" 1170 "- locallimit: reached to local system limits when sending a message.\n" 1173 "The exit status is:\n" 1174 "0 on complete success.\n" 1175 "1 for a general error.\n" 1176 "2 if an error is found in the command line arguments.\n" 1177 "3 if there are no general failures in operation, but one or more\n" 1178 " exchanges are not successfully completed.\n";
1183 std::cout <<
"VERSION: " << VERSION << std::endl;
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
bool parse(int argc, char **const argv, bool print_cmd_line=false)
Parse command line.
bool isUseRelayedV6() const
Check if generated DHCPv6 messages should appear as relayed.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
const char *const * perfdhcp_config_report
link-layer + time, see RFC3315, section 11.2
void set(const Type lease_type)
Sets the lease type code.
#define DHCP_IPV4_BROADCAST_ADDRESS
int getServerIdOffset() const
Returns template offset for server-ID.
boost::shared_ptr< Option > OptionPtr
bool is(const Type lease_type) const
Checks if lease type has the specified code.
static CommandOptions & instance()
CommandOptions is a singleton class.
bool isUseFirst() const
Check if server-ID to be taken from first package.
Handles network interfaces, transmission and reception.
std::vector< std::string > getTemplateFiles() const
Returns template file names.
uint8_t getIpVersion() const
Returns IP version.
ExchangeMode getExchangeMode() const
Returns packet exchange mode.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
void fromCommandLine(const std::string &cmd_line_arg)
Sets the lease type from the command line argument.
#define ALL_DHCP_RELAY_AGENTS_AND_SERVERS
bool isBroadcast() const
Checks if broadcast address is to be used.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void version() const
Print program version.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
std::vector< int > getTransactionIdOffset() const
brief Returns template offsets for xid.
void printCommandLine() const
Print command line arguments.
LeaseType getLeaseType() const
\ brief Returns the type of lease being requested.
std::vector< int > getRandomOffset() const
Returns template offsets for rnd.
int getReleaseRate() const
Returns a rate at which DHCPv6 Release messages are sent.
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
A generic exception that is thrown when an unexpected error condition occurs.
void usage() const
Print usage.
std::vector< double > getDropTime() const
Returns drop time.
std::string toText() const
Return textual representation of the lease type.
bool includes(const Type lease_type) const
Checks if lease type implies request for the address, prefix (or both) as specified by the function a...
int getLocalPort() const
Returns local port number.
Defines the logger used by the top-level component of kea-dhcp-ddns.
const char *const config_report[]
int getElapsedTimeOffset() const
Returns template offset for elapsed time.
void reset()
Reset to defaults.
std::vector< int > getMaxDrop() const
Returns maximum drops number.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
std::vector< int > getNumRequests() const
Returns maximum number of exchanges.
int getRate() const
Returns exchange rate.
std::vector< double > getMaxDropPercentage() const
Returns maximal percentage of drops.
std::string getMacListFile() const
Returns location of the file containing list of MAC addresses.
int getRequestedIpOffset() const
Returns template offset for requested IP.
bool isRapidCommit() const
Check if rapid commit option used.
int getRenewRate() const
Returns a rate at which DHCPv6 Renew messages are sent.