Browse Source

Add unreachable server processing for address selection logic

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac356@3725 e5f2f494-b856-4b98-b285-d166d9295462
Haidong Wang 14 years ago
parent
commit
5925fd66c3

+ 15 - 5
src/lib/nsas/address_entry.h

@@ -37,7 +37,7 @@ public:
     /// \param address Address object representing this address
     /// \param rtt Initial round-trip time
     AddressEntry(const asiolink::IOAddress& address, uint32_t rtt = 0) :
-        address_(address), rtt_(rtt)
+        address_(address), rtt_(rtt), dead_until_(0)
     {}
 
     /// \return Address object
@@ -46,7 +46,12 @@ public:
     }
 
     /// \return Current round-trip time
-    uint32_t getRTT() const {
+    uint32_t getRTT() {
+        if(dead_until_ != 0 && time(NULL) >= dead_until_){
+            dead_until_ = 0;
+            rtt_ = 1; //reset the rtt to a small value so it has an opportunity to be updated
+        }
+
         return rtt_;
     }
 
@@ -54,7 +59,11 @@ public:
     ///
     /// \param rtt New RTT to be associated with this address
     void setRTT(uint32_t rtt) {
-        rtt_ = rtt;     // TODO: Modify to use weighting formula
+        if(rtt == UNREACHABLE){
+            dead_until_ = time(NULL) + 5*60;//Cache the unreachable server for 5 minutes (RFC2308 sec7.2)
+        }
+
+        rtt_ = rtt;
     }
 
     /// Mark address as unreachable.
@@ -65,8 +74,8 @@ public:
     /// Check if address is unreachable
     ///
     /// \return true if the address is unreachable, false if not
-    bool isUnreachable() const {
-        return (rtt_ == UNREACHABLE);
+    bool isUnreachable() {
+        return (getRTT() == UNREACHABLE); // The getRTT() will check the cache time for unreachable server
     }
 
     /// \return true if the object is a V4 address
@@ -85,6 +94,7 @@ public:
 private:
     asiolink::IOAddress address_;       ///< Address
     uint32_t        rtt_;               ///< Round-trip time
+    time_t  dead_until_;                ///< Dead time for unreachable server
 };
 
 }   // namespace dns

+ 7 - 3
src/lib/nsas/nameserver_entry.cc

@@ -244,16 +244,20 @@ void NameserverEntry::setAddressUnreachable(const IOAddress& address) {
 // Each address has a probability to be selected if multiple addresses are available
 // The weight factor is equal to 1/(rtt*rtt), then all the weight factors are normalized
 // to make the sum equal to 1.0
-void NameserverEntry::updateAddressSelector(const std::vector<AddressEntry>& addresses, 
+void NameserverEntry::updateAddressSelector(std::vector<AddressEntry>& addresses, 
         WeightedRandomIntegerGenerator& selector)
 {
     vector<double> probabilities;
-    for(vector<AddressEntry>::const_iterator it = addresses.begin(); 
+    for(vector<AddressEntry>::iterator it = addresses.begin(); 
             it != addresses.end(); ++it){
         uint32_t rtt = (*it).getRTT();
         if(rtt == 0) isc_throw(RTTIsZero, "The RTT is 0");
 
-        probabilities.push_back(1.0/(rtt*rtt));
+        if(rtt == AddressEntry::UNREACHABLE) {
+            probabilities.push_back(0);
+        } else {
+            probabilities.push_back(1.0/(rtt*rtt));
+        }
     }
     // Calculate the sum
     double sum = accumulate(probabilities.begin(), probabilities.end(), 0.0);

+ 1 - 1
src/lib/nsas/nameserver_entry.h

@@ -225,7 +225,7 @@ private:
     ///
     /// \param addresses The address list
     /// \param selector Weighted random generator
-    void updateAddressSelector(const std::vector<AddressEntry>& addresses, 
+    void updateAddressSelector(std::vector<AddressEntry>& addresses, 
             WeightedRandomIntegerGenerator& selector);
 
     boost::mutex    mutex_;                              ///< Mutex protecting this object

+ 18 - 0
src/lib/nsas/tests/nameserver_entry_unittest.cc

@@ -464,6 +464,24 @@ TEST_F(NameserverEntryTest, AddressSelection) {
     ASSERT_EQ(4, (int)(c1*1.0/c2 + 0.5));
     // c1 should be (3*3) times of c3
     ASSERT_EQ(9, (int)(c1*1.0/c3 + 0.5));
+
+    // Test unreachable address
+    ns->setAddressRTT(v4Addresses[0].getAddress(), 1);
+    ns->setAddressRTT(v4Addresses[1].getAddress(), 100);
+    ns->setAddressUnreachable(v4Addresses[2].getAddress());
+    c1 = c2 = c3 = 0;
+    for(int i = 0; i < 100000; ++i){
+        ns.get()->getAddress(ns, ns_address, AF_INET);
+        asiolink::IOAddress io_address = ns_address.getAddress();
+        if(io_address.toText() == v4Addresses[0].getAddress().toText()) ++c1;
+        else if(io_address.toText() == v4Addresses[1].getAddress().toText()) ++c2;
+        else if(io_address.toText() == v4Addresses[2].getAddress().toText()) ++c3;
+    }
+
+    // The 3rd address should not be selected again
+    ASSERT_EQ(0, c3);
+
+    // TODO: The unreachable server should be changed to reachable after 5minutes, but how to test?
 }
 
 // Test the RTT is updated smoothly