// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. #ifndef __COMMAND_OPTIONS_H #define __COMMAND_OPTIONS_H #include #include #include namespace isc { namespace perfdhcp { /// \brief Command Options /// /// This class is responsible for parsing the command-line and storing the /// specified options. /// class CommandOptions : public boost::noncopyable { public: /// 2-way (cmd line param -i) or 4-way exchanges enum ExchangeMode { DO_SA, DORA_SARR }; /// CommandOptions is a singleton class. This method returns reference /// to its sole instance. /// /// \return the only existing instance of command options static CommandOptions& instance(); /// \brief Reset to defaults /// /// Reset data members to default values. This is specifically /// useful when unit tests are performed using different /// command line options. void reset(); /// \brief Parse command line /// /// Parses the command line and stores the selected options /// in class data members. /// /// \param argc Argument count passed to main(). /// \param argv Argument value array passed to main(). /// \throws isc::InvalidParameter if parse fails void parse(int argc, char** const argv); /// \brief Returns IP version /// /// \return IP version to be used uint8_t getIpVersion() const { return ipversion_; } /// \brief Returns packet exchange mode /// /// \return packet exchange mode ExchangeMode getExchangeMode() const { return exchange_mode_; } /// \brief Returns echange rate /// /// \return exchange rate per second int getRate() const { return rate_; } /// \brief Returns delay between two performance reports /// /// \return delay between two consecutive performance reports int getReportDelay() const { return report_delay_; } /// \brief Returns number of simulated clients /// /// \return number of simulated clients uint32_t getClientsNum() const { return clients_num_; } /// \brief Returns MAC address prefix /// /// \ return MAC address prefix to simulate different clients std::vector getMacPrefix() const { return mac_prefix_; } /// \brief Returns DUID prefix /// /// \return DUID prefix to simulate different clients std::vector getDuidPrefix() const { return duid_prefix_; } /// \brief Returns base values /// /// \return all base values specified std::vector getBase() const { return base_; } /// \brief Returns maximum number of exchanges /// /// \return number of exchange requests before test is aborted std::vector getNumRequests() const { return num_request_; } /// \brief Returns test period /// /// \return test period before it is aborted int getPeriod() const { return period_; } /// \brief Returns drop time /// /// The method returns maximum time elapsed from /// sending the packet before it is assumed dropped. /// /// \return return time before request is assumed dropped std::vector getDropTime() const { return drop_time_; } /// \brief Returns maximum drops number /// /// Returns maximum number of packet drops before /// aborting a test. /// /// \return maximum number of dropped requests std::vector getMaxDrop() const { return max_drop_; } /// \brief Returns maximal percentage of drops /// /// Returns maximal percentage of packet drops /// before aborting a test. /// /// \return maximum percentage of lost requests std::vector getMaxDropPercentage() const { return max_pdrop_; } /// \brief Returns local address or interface name /// /// \return local address or interface name std::string getLocalName() const { return localname_; } /// \brief Checks if interface name was used /// /// The method checks if interface name was used /// rather than address. /// /// \return true if interface name was used bool isInterface() const { return is_interface_; } /// \brief Returns number of preload exchanges /// /// \return number of preload exchanges int getPreload() const { return preload_; } /// \brief Returns aggressivity value /// /// \return aggressivity value int getAggressivity() const { return aggressivity_; } /// \brief Returns local port number /// /// \return local port number int getLocalPort() const { return local_port_; } /// \brief Checks if seed provided /// /// \return true if seed was provided bool isSeeded() const { return seeded_; } /// \brief Returns radom seed /// /// \return random seed uint32_t getSeed() const { return seed_; } /// \brief Checks if broadcast address is to be used /// /// \return true if broadcast address is to be used bool isBroadcast() const { return broadcast_; } /// \brief Check if rapid commit option used /// /// \return true if rapid commit option is used bool isRapidCommit() const { return rapid_commit_; } /// \brief Check if server-ID to be taken from first package /// /// \return true if server-iD to be taken from first package bool isUseFirst() const { return use_first_; } /// \brief Returns template file names /// /// \return template file names std::vector getTemplateFiles() const { return template_file_; } /// brief Returns template offsets for xid /// /// \return template offsets for xid std::vector getTransactionIdOffset() const { return xid_offset_; } /// \brief Returns template offsets for rnd /// /// \return template offsets for rnd std::vector getRandomOffset() const { return rnd_offset_; } /// \brief Returns template offset for elapsed time /// /// \return template offset for elapsed time int getElapsedTimeOffset() const { return elp_offset_; } /// \brief Returns template offset for server-ID /// /// \return template offset for server-ID int getServerIdOffset() const { return sid_offset_; } /// \brief Returns template offset for requested IP /// /// \return template offset for requested IP int getRequestedIpOffset() const { return rip_offset_; } /// \brief Returns diagnostic selectors /// /// \return diagnostics selector std::string getDiags() const { return diags_; } /// \brief Returns wrapped command /// /// \return wrapped command (start/stop) std::string getWrapped() const { return wrapped_; } /// \brief Returns server name /// /// \return server name std::string getServerName() const { return server_name_; } /// \brief Print usage /// /// Prints perfdhcp usage void usage() const; /// \brief Print program version /// /// Prints perfdhcp version void version() const; private: /// \brief Default Constructor /// /// Private constructor as this is a singleton class. /// Use CommandOptions::instance() to get instance of it. CommandOptions() { reset(); } /// \brief Initializes class members based command line /// /// Reads each command line parameter and sets class member values /// /// \param argc Argument count passed to main(). /// \param argv Argument value array passed to main(). /// \throws isc::InvalidParameter if command line options initialization fails void initialize(int argc, char** argv); /// \brief Validates initialized options /// /// \throws isc::InvalidParameter if command line validation fails void validate() const; /// \brief Throws !InvalidParameter exception if condition is true /// /// Convenience function that throws an InvalidParameter exception if /// the condition argument is true /// /// \param condition Condition to be checked /// \param errmsg Error message in exception /// \throws isc::InvalidParameter if condition argument true inline void check(bool condition, const std::string& errmsg) const; /// \brief Casts command line argument to positive integer /// /// \param errmsg Error message if lexical cast fails /// \throw InvalidParameter if lexical cast fails int positiveInteger(const std::string& errmsg) const; /// \brief Casts command line argument to non-negative integer /// /// \param errmsg Error message if lexical cast fails /// \throw InvalidParameter if lexical cast fails int nonNegativeInteger(const std::string& errmsg) const; /// \brief Returns command line string if it is not empty /// /// \param errmsg Error message if string is empty /// \throw InvalidParameter if string is empty std::string nonEmptyString(const std::string& errmsg) const; /// \brief Set number of clients /// /// Interprets the getopt() "opt" global variable as the number of clients /// (a non-negative number). This value is specified by the "-R" switch. /// /// \throw InvalidParameter if -R is wrong void initClientsNum(); /// \brief Decodes base provided with -b /// /// Function decodes argument of -b switch, which /// specifies a base value used to generate unique /// mac or duid values in packets sent to system /// under test. /// The following forms of switch arguments are supported: /// - -b mac=00:01:02:03:04:05 /// - -b duid=0F1234 (duid can be up to 128 hex digits) // Function will decode 00:01:02:03:04:05 and/or /// 0F1234 respectively and initialize mac_prefix_ /// and/or duid_prefix_ members /// /// \param base Base in string format /// \throws isc::InvalidParameter if base is invalid void decodeBase(const std::string& base); /// \brief Decodes base MAC address provided with -b /// /// Function decodes parameter given as -b mac=00:01:02:03:04:05 /// The function will decode 00:01:02:03:04:05 initialize mac_prefix_ /// class member. /// Provided MAC address is for example only /// /// \param base Base string given as -b mac=00:01:02:03:04:05 /// \throws isc::InvalidParameter if mac address is invalid void decodeMac(const std::string& base); /// \brief Decodes base DUID provided with -b /// /// Function decodes parameter given as -b duid=0F1234 /// The function will decode 0F1234 and initialize duid_prefix_ /// class member. /// Provided DUID is for example only. /// /// \param base Base string given as -b duid=0F1234 /// \throws isc::InvalidParameter if DUID is invalid void decodeDuid(const std::string& base); /// \brief Converts two-digit hexadecimal string to a byte /// /// \param hex_text Hexadecimal string e.g. AF /// \throw isc::InvalidParameter if string does not represent hex byte uint8_t convertHexString(const std::string& hex_text) const; uint8_t ipversion_; ///< IP protocol version to be used, expected values are: ///< 4 for IPv4 and 6 for IPv6, default value 0 means "not set" ExchangeMode exchange_mode_; ///< Packet exchange mode (e.g. DORA/SARR) int rate_; ///< Rate in exchange per second int report_delay_; ///< Delay between generation of two consecutive ///< performance reports uint32_t clients_num_; ///< Number of simulated clients (aka randomization range). std::vector mac_prefix_; ///< MAC address prefix used to generate unique DUIDs ///< for simulated clients. std::vector duid_prefix_; ///< DUID prefix used to generate unique DUIDs for ///< simulated clients std::vector base_; ///< Collection of base values specified with -b ///< options. Supported "bases" are mac= and duid= std::vector num_request_; ///< Number of 2 or 4-way exchanges to perform int period_; ///< Test period in seconds uint8_t drop_time_set_; ///< Indicates number of -d parameters specified by user. ///< If this value goes above 2, command line parsing fails. std::vector drop_time_; ///< Time to elapse before request is lost. The fisrt value of ///< two-element vector refers to DO/SA exchanges, ///< second value refers to RA/RR. Default values are { 1, 1 } std::vector max_drop_; ///< Maximum number of drops request before aborting test. ///< First value of two-element vector specifies maximum ///< number of drops for DO/SA exchange, second value ///< specifies maximum number of drops for RA/RR. std::vector max_pdrop_; ///< Maximal percentage of lost requests before aborting test. ///< First value of two-element vector specifies percentage for ///< DO/SA exchanges, second value for RA/RR. std::string localname_; ///< Local address or interface specified with -l option. bool is_interface_; ///< Indicates that specified value with -l is ///< rather interface (not address) int preload_; ///< Number of preload packets. Preload packets are used to ///< initiate communication with server before doing performance ///< measurements. int aggressivity_; ///< Number of exchanges sent before next pause. int local_port_; ///< Local port number (host endian) bool seeded_; ///< Indicates that randomization seed was provided. uint32_t seed_; ///< Randomization seed. bool broadcast_; ///< Indicates that we use broadcast address. bool rapid_commit_; ///< Indicates that we do rapid commit option. bool use_first_; ///< Indicates that we take server id from first received packet. std::vector template_file_; ///< Packet template file names. These files store template packets ///< that are used for initiating echanges. Template packets ///< read from files are later tuned with variable data. std::vector xid_offset_; ///< Offset of transaction id in template files. First vector ///< element points to offset for DISCOVER/SOLICIT messages, ///< second element points to trasaction id offset for ///< REQUEST messages std::vector rnd_offset_; ///< Random value offset in templates. Random value offset ///< points to last octet of DUID. Up to 4 last octets of ///< DUID are randomized to simulate differnt clients. int elp_offset_; ///< Offset of elapsed time option in template packet. int sid_offset_; ///< Offset of server id option in template packet. int rip_offset_; ///< Offset of requested ip data in template packet/ std::string diags_; ///< String representing diagnostic selectors specified ///< by user with -x. std::string wrapped_; ///< Wrapped command specified as -w. Expected ///< values are start and stop. std::string server_name_; ///< Server name specified as last argument of command line. }; } // namespace perfdhcp } // namespace isc #endif // __COMMAND_OPTIONS_H