]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#931] simulate v4 traffic from different subnets
authorWlodek Wencel <wlodek@isc.org>
Mon, 2 Mar 2020 12:59:11 +0000 (13:59 +0100)
committerRazvan Becheriu <razvan@isc.org>
Fri, 13 Mar 2020 07:21:40 +0000 (07:21 +0000)
src/bin/perfdhcp/command_options.cc
src/bin/perfdhcp/command_options.h
src/bin/perfdhcp/test_control.cc
src/bin/perfdhcp/tests/command_options_unittest.cc
src/bin/perfdhcp/tests/testdata/Makefile.am
src/bin/perfdhcp/tests/testdata/giaddr [new file with mode: 0644]

index e43d3ca5f1f64fd50e6da975241f1133e6f2e6ed..d7c8be38e26a1fb7c0fd3de2350eb047a8996421 100644 (file)
@@ -14,6 +14,7 @@
 #include <dhcp/option.h>
 #include <cfgrpt/config_report.h>
 #include <util/encode/hex.h>
+#include <asiolink/io_error.h>
 
 #include <boost/lexical_cast.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -123,6 +124,9 @@ CommandOptions::reset() {
     addr_unique_ = false;
     mac_list_file_.clear();
     mac_list_.clear();
+    giaddr_list_file_.clear();
+    giaddr_list_.clear();
+    multi_subnet_ = false;
     num_request_.clear();
     exit_wait_time_ = 0;
     period_ = 0;
@@ -233,7 +237,7 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
     // they will be tuned and validated elsewhere
     while((opt = getopt_long(argc, argv,
                              "huv46A:r:t:R:b:n:p:d:D:l:P:a:L:N:M:s:iBc1"
-                             "T:X:O:o:E:S:I:x:W:w:e:f:F:g:",
+                             "J:T:X:O:o:E:S:I:x:W:w:e:f:F:g:",
                              long_options, NULL)) != -1) {
         stream << " -" << static_cast<char>(opt);
         if (optarg) {
@@ -373,6 +377,11 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
                                           " positive integer");
             break;
 
+        case 'J':
+            giaddr_list_file_ = std::string(optarg);
+            loadGiaddr();
+            break;
+
         case 'l':
             localname_ = std::string(optarg);
             initIsInterface();
@@ -816,6 +825,31 @@ CommandOptions::convertHexString(const std::string& text) const {
     return ui;
 }
 
+bool CommandOptions::validateIP(const std::string& line) {
+    try {
+        asiolink::IOAddress ip_address_ = isc::asiolink::IOAddress(line);
+        // let's silence not used warning
+        (void) ip_address_;
+    } catch (const isc::asiolink::IOError& e) {
+        return (true);
+    }
+    giaddr_list_.push_back(line);
+    multi_subnet_ = true;
+    return (false);
+}
+
+void CommandOptions::loadGiaddr() {
+    std::string line;
+    std::ifstream infile(giaddr_list_file_.c_str());
+    size_t cnt = 0;
+    while (std::getline(infile, line)) {
+        cnt++;
+        stringstream tmp;
+        tmp << "invalid address in line: "<< cnt;
+        check(validateIP(line), tmp.str());
+    }
+}
+
 void CommandOptions::loadMacs() {
     std::string line;
     std::ifstream infile(mac_list_file_.c_str());
@@ -1177,6 +1211,9 @@ CommandOptions::usage() const {
         "    whether -6 is given.\n"
         "-I<ip-offset>: Offset of the (DHCPv4) IP address in the requested-IP\n"
         "    option / (DHCPv6) IA_NA option in the (second/request) template.\n"
+        "-J<giaddr-list-file>: Text file that include multiple addresses.\n"
+        "    If provided perfdhcp will choose randomly one of addresses for each\n"
+        "    exchange.\n"
         "-l<local-addr|interface>: For DHCPv4 operation, specify the local\n"
         "    hostname/address to use when communicating with the server.  By\n"
         "    default, the interface address through which traffic would\n"
index c243d392ad7c198d67b24784dcc727fafe36db6b..c8e1cadfa708eaf17bdfc488b93b79d9d73f72f6 100644 (file)
@@ -370,6 +370,25 @@ public:
     /// \return server name.
     std::string getServerName() const { return server_name_; }
 
+    /// \brief Returns giaddr file location.
+    ///
+    /// \return giaddr list file location.
+    std::string getGiaddrListFile() const { return giaddr_list_file_; }
+
+    /// \brief Returns list of giaddr addresses.
+    ///
+    /// \return list of giaddr.
+    std::vector<std::string> getGiaddrList() const { return giaddr_list_; }
+
+    /// \brief Returns random giaddr.
+    ///
+    /// \return single string containing giaddr.
+    std::string getRandGiaddr() { return giaddr_list_[rand() % giaddr_list_.size()];}
+
+    /// \brief Check if multi subnet mode is enabled
+    ///
+    /// \return true if multisubnet mode is enabled.
+    bool checkMultiSubnet() { return multi_subnet_; }
 
     /// \brief Find if diagnostic flag has been set.
     ///
@@ -524,6 +543,15 @@ private:
     /// mac_list_ vector.
     bool decodeMacString(const std::string& line);
 
+    /// \brief Opens the text file containgin list of addresses (one per line).
+    void loadGiaddr();
+
+    /// \brief Checks if loaded giaddr from text file are correct,
+    /// adds them to giaddr_list_.
+    ///
+    /// \return true if address is incorrect
+    bool validateIP(const std::string& line);
+
     /// IP protocol version to be used, expected values are:
     /// 4 for IPv4 and 6 for IPv6, default value 0 means "not set".
     uint8_t ipversion_;
@@ -641,6 +669,11 @@ private:
     /// List of MAC addresses loaded from a file.
     std::vector<std::vector<uint8_t> > mac_list_;
 
+    std::string giaddr_list_file_;
+
+    std::vector<std::string> giaddr_list_;
+
+    bool multi_subnet_;
     /// Offset of transaction id in template files. First vector
     /// element points to offset for DISCOVER/SOLICIT messages,
     /// second element points to transaction id offset for
index f99bcf4eae39098e60d011b18ab28b48e2b52b56..ce28140a0f3ecb205a2a82f953e1f95538392c9f 100644 (file)
@@ -1315,10 +1315,10 @@ TestControl::sendRequest4(const dhcp::Pkt4Ptr& discover_pkt4,
     OptionPtr opt_parameter_list =
         Option::factory(Option::V4, DHO_DHCP_PARAMETER_REQUEST_LIST);
     pkt4->addOption(opt_parameter_list);
-    // Set client's and server's ports as well as server's address,
-    // and local (relay) address.
+    // Set client's and server's ports as well as server's address
     setDefaults4(pkt4);
-
+    // Override relay address
+    pkt4->setGiaddr(offer_pkt4->getGiaddr());
     // Add any extra options that user may have specified.
     addExtraOpts(pkt4);
 
@@ -1721,8 +1721,13 @@ TestControl::setDefaults4(const Pkt4Ptr& pkt) {
     pkt->setRemoteAddr(IOAddress(options_.getServerName()));
     // Set local address.
     pkt->setLocalAddr(IOAddress(socket_.addr_));
-    // Set relay (GIADDR) address to local address.
-    pkt->setGiaddr(IOAddress(socket_.addr_));
+    // Set relay (GIADDR) address to local address if multiple
+    // subnet mode is not enabled
+    if (!options_.checkMultiSubnet()) {
+        pkt->setGiaddr(IOAddress(socket_.addr_));
+    } else {
+        pkt->setGiaddr(IOAddress(options_.getRandGiaddr()));
+    }
     // Pretend that we have one relay (which is us).
     pkt->setHops(1);
 }
index 8bedecf12a723a05ab9af7158adedb3621186639..677090425142556f5b7dd0131d098e74c2b5e57e 100644 (file)
@@ -832,6 +832,17 @@ TEST_F(CommandOptionsTest, LoadMacsFromFile) {
     EXPECT_EQ(4, m.size());
 }
 
+TEST_F(CommandOptionsTest, LoadGiaddrFromFile) {
+    CommandOptions opt;
+    std::string giaddr_list_full_path = getFullPath("giaddr");
+    std::ostringstream cmd;
+    cmd << "perfdhcp -J " << giaddr_list_full_path << " abc";
+    EXPECT_NO_THROW(process(opt, cmd.str()));
+    EXPECT_EQ(giaddr_list_full_path, opt.getGiaddrListFile());
+    EXPECT_TRUE(opt.checkMultiSubnet());
+    EXPECT_EQ(5, opt.getGiaddrList().size());
+}
+
 TEST_F(CommandOptionsTest, LoadMacsFromFileNegativeCases) {
     CommandOptions opt;
     // Negative test cases
index 30c3329de6c7a0146ff662afd4ae8e967139da47..1505af7bcf2520200bcc464bfcb58da07b2c5989 100644 (file)
@@ -2,4 +2,4 @@ SUBDIRS = .
 
 EXTRA_DIST = discover-example.hex request4-example.hex
 EXTRA_DIST += solicit-example.hex request6-example.hex
-EXTRA_DIST += mac-list.txt
+EXTRA_DIST += mac-list.txt giaddr
diff --git a/src/bin/perfdhcp/tests/testdata/giaddr b/src/bin/perfdhcp/tests/testdata/giaddr
new file mode 100644 (file)
index 0000000..6d3db81
--- /dev/null
@@ -0,0 +1,5 @@
+100.95.0.1
+20.86.12.1
+101.64.4.1
+1.86.0.1
+92.86.238.1