IPv6InterfaceData.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Andras Varga
00003 // Copyright (C) 2005 Wei Yang, Ng
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <sstream>
00020 #include <algorithm>
00021 #include "IPv6InterfaceData.h"
00022 
00023 //FIXME invoked changed() from state-changing methods, to trigger notification...
00024 
00025 
00026 IPv6InterfaceData::IPv6InterfaceData()
00027 {
00028     /*******************Setting host/node/router Protocol Constants************/
00029     routerConstants.maxInitialRtrAdvertInterval = IPv6_MAX_INITIAL_RTR_ADVERT_INTERVAL;
00030     routerConstants.maxInitialRtrAdvertisements = IPv6_MAX_INITIAL_RTR_ADVERTISEMENTS;
00031     routerConstants.maxFinalRtrAdvertisements = IPv6_MAX_FINAL_RTR_ADVERTISEMENTS;
00032     routerConstants.minDelayBetweenRAs = IPv6_MIN_DELAY_BETWEEN_RAS;
00033     routerConstants.maxRADelayTime = IPv6_MAX_RA_DELAY_TIME;
00034 
00035     hostConstants.maxRtrSolicitationDelay = IPv6_MAX_RTR_SOLICITATION_DELAY;
00036     hostConstants.rtrSolicitationInterval = IPv6_RTR_SOLICITATION_INTERVAL;
00037     hostConstants.maxRtrSolicitations = IPv6_MAX_RTR_SOLICITATIONS;
00038 
00039     nodeConstants.maxMulticastSolicit = IPv6_MAX_MULTICAST_SOLICIT;
00040     nodeConstants.maxUnicastSolicit = IPv6_MAX_UNICAST_SOLICIT;
00041     nodeConstants.maxAnycastDelayTime = IPv6_MAX_ANYCAST_DELAY_TIME;
00042     nodeConstants.maxNeighbourAdvertisement = IPv6_MAX_NEIGHBOUR_ADVERTISEMENT;
00043     nodeConstants.reachableTime = IPv6_REACHABLE_TIME;
00044     nodeConstants.retransTimer = IPv6_RETRANS_TIMER;
00045     nodeConstants.delayFirstProbeTime = IPv6_DELAY_FIRST_PROBE_TIME;
00046     nodeConstants.minRandomFactor = IPv6_MIN_RANDOM_FACTOR;
00047     nodeConstants.maxRandomFactor = IPv6_MAX_RANDOM_FACTOR;
00048 
00049     /*******************Setting host/node/router variables*********************/
00050     nodeVars.dupAddrDetectTransmits = IPv6_DEFAULT_DUPADDRDETECTTRANSMITS;
00051 
00052     hostVars.linkMTU = IPv6_MIN_MTU;
00053     hostVars.curHopLimit = IPv6_DEFAULT_ADVCURHOPLIMIT;//value specified in RFC 1700-can't find it
00054     hostVars.baseReachableTime = IPv6_REACHABLE_TIME;
00055     hostVars.reachableTime = generateReachableTime(_getMinRandomFactor(),
00056         _getMaxRandomFactor(), getBaseReachableTime());
00057     hostVars.retransTimer = IPv6_RETRANS_TIMER;
00058 
00059     //rtrVars.advSendAdvertisements is set in RoutingTable6.cc:line 143
00060     rtrVars.maxRtrAdvInterval = IPv6_DEFAULT_MAX_RTR_ADV_INT;
00061     rtrVars.minRtrAdvInterval = 0.33*rtrVars.maxRtrAdvInterval;
00062     rtrVars.advManagedFlag = false;
00063     rtrVars.advOtherConfigFlag = false;
00064     rtrVars.advLinkMTU = IPv6_MIN_MTU;
00065     rtrVars.advReachableTime = IPv6_DEFAULT_ADV_REACHABLE_TIME;
00066     rtrVars.advRetransTimer = IPv6_DEFAULT_ADV_RETRANS_TIMER;
00067     rtrVars.advCurHopLimit = IPv6_DEFAULT_ADVCURHOPLIMIT;
00068     rtrVars.advDefaultLifetime = 3*rtrVars.maxRtrAdvInterval;
00069 #if USE_MOBILITY
00070     if (rtrVars.advDefaultLifetime<1)
00071         rtrVars.advDefaultLifetime = 1;
00072 #endif
00073 }
00074 
00075 std::string IPv6InterfaceData::info() const
00076 {
00077     // FIXME FIXME FIXME FIXME info() should never print a newline
00078     std::ostringstream os;
00079     os << "IPv6:{" << endl;
00080     for (int i=0; i<getNumAddresses(); i++)
00081     {
00082         os << (i?"\t            , ":"\tAddrs:") << getAddress(i)
00083            << "(" << IPv6Address::scopeName(getAddress(i).getScope())
00084            << (isTentativeAddress(i)?" tent":"") << ") "
00085            << " expiryTime: " << (addresses[i].expiryTime==0 ? "inf" : SIMTIME_STR(addresses[i].expiryTime))
00086            << " prefExpiryTime: " << (addresses[i].prefExpiryTime==0 ? "inf" : SIMTIME_STR(addresses[i].prefExpiryTime))
00087            << endl;
00088     }
00089 
00090     for (int i=0; i<getNumAdvPrefixes(); i++)
00091     {
00092         const AdvPrefix& a = getAdvPrefix(i);
00093         os << (i?", ":"\tAdvPrefixes: ") << a.prefix << "/" << a.prefixLength << "("
00094            << (a.advOnLinkFlag?"":"off-link ")
00095            << (a.advAutonomousFlag?"":"non-auto ");
00096         if (a.advValidLifetime==0)
00097            os  << "lifetime:inf";
00098         else if (a.advValidLifetime>0)
00099            os  << "expires:" << a.advValidLifetime;
00100         else
00101            os  << "lifetime:+" << (-1 * a.advValidLifetime);
00102         os << ")" << endl;
00103     }
00104     os << " ";
00105 
00106     // uncomment the following as needed!
00107     os << "\tNode:";
00108     os << " dupAddrDetectTrans=" << nodeVars.dupAddrDetectTransmits;
00109     //os << " curHopLimit=" << hostVars.curHopLimit;
00110     //os << " retransTimer=" << hostVars.retransTimer;
00111     //os << " baseReachableTime=" << hostVars.baseReachableTime;
00112     os << " reachableTime=" << hostVars.reachableTime << endl;
00113 
00114     if (rtrVars.advSendAdvertisements)
00115     {
00116         os << "\tRouter:";
00117         os << " maxRtrAdvInt=" << rtrVars.maxRtrAdvInterval;
00118         os << " minRtrAdvInt=" << rtrVars.minRtrAdvInterval << endl;
00119         //os << " advManagedFlag=" << rtrVars.advManagedFlag;
00120         //os << " advOtherFlag=" << rtrVars.advOtherFlag;
00121         //os << " advLinkMTU=" << rtrVars.advLinkMTU;
00122         //os << " advReachableTime=" << rtrVars.advReachableTime;
00123         //os << " advRetransTimer=" << rtrVars.advRetransTimer;
00124         //os << " advCurHopLimit=" << rtrVars.advCurHopLimit;
00125         //os << " advDefaultLifetime=" << rtrVars.advDefaultLifetime;
00126     }
00127 
00128     os << "   }" << endl;
00129     return os.str();
00130 }
00131 
00132 std::string IPv6InterfaceData::detailedInfo() const
00133 {
00134     return info(); // TBD this could be improved: multi-line text, etc
00135 }
00136 
00137 void IPv6InterfaceData::assignAddress(const IPv6Address& addr, bool tentative,
00138                                       simtime_t expiryTime, simtime_t prefExpiryTime)
00139 {
00140     addresses.push_back(AddressData());
00141     AddressData& a = addresses.back();
00142     a.address = addr;
00143     a.tentative = tentative;
00144     a.expiryTime = expiryTime;
00145     a.prefExpiryTime = prefExpiryTime;
00146     choosePreferredAddress();
00147 }
00148 
00149 void IPv6InterfaceData::updateMatchingAddressExpiryTimes(const IPv6Address& prefix, int length,
00150                                                          simtime_t expiryTime, simtime_t prefExpiryTime)
00151 {
00152     for (AddressDataVector::iterator it=addresses.begin(); it!=addresses.end(); it++)
00153     {
00154         if (it->address.matches(prefix,length))
00155         {
00156             it->expiryTime = expiryTime;
00157             it->prefExpiryTime = prefExpiryTime;
00158         }
00159     }
00160     choosePreferredAddress();
00161 }
00162 
00163 int IPv6InterfaceData::findAddress(const IPv6Address& addr) const
00164 {
00165     for (AddressDataVector::const_iterator it=addresses.begin(); it!=addresses.end(); it++)
00166         if (it->address==addr)
00167             return it-addresses.begin();
00168     return -1;
00169 }
00170 
00171 const IPv6Address& IPv6InterfaceData::getAddress(int i) const
00172 {
00173     ASSERT(i>=0 && i<(int)addresses.size());
00174     return addresses[i].address;
00175 }
00176 
00177 bool IPv6InterfaceData::isTentativeAddress(int i) const
00178 {
00179     ASSERT(i>=0 && i<(int)addresses.size());
00180     return addresses[i].tentative;
00181 }
00182 
00183 bool IPv6InterfaceData::hasAddress(const IPv6Address& addr) const
00184 {
00185     return findAddress(addr)!=-1;
00186 }
00187 
00188 bool IPv6InterfaceData::matchesSolicitedNodeMulticastAddress(const IPv6Address& solNodeAddr) const
00189 {
00190     for (AddressDataVector::const_iterator it=addresses.begin(); it!=addresses.end(); it++)
00191         if (it->address.formSolicitedNodeMulticastAddress()==solNodeAddr)
00192             return true;
00193     return false;
00194 }
00195 
00196 bool IPv6InterfaceData::isTentativeAddress(const IPv6Address& addr) const
00197 {
00198     int k = findAddress(addr);
00199     return k!=-1 && addresses[k].tentative;
00200 }
00201 
00202 void IPv6InterfaceData::permanentlyAssign(const IPv6Address& addr)
00203 {
00204     int k = findAddress(addr);
00205     ASSERT(k!=-1);
00206     addresses[k].tentative = false;
00207     choosePreferredAddress();
00208 }
00209 
00210 const IPv6Address& IPv6InterfaceData::getLinkLocalAddress() const
00211 {
00212     for (AddressDataVector::const_iterator it=addresses.begin(); it!=addresses.end(); it++)
00213         if (it->address.isLinkLocal())  // FIXME and valid
00214             return it->address;
00215     return IPv6Address::UNSPECIFIED_ADDRESS;
00216 }
00217 
00218 void IPv6InterfaceData::removeAddress(const IPv6Address& address)
00219 {
00220     int k = findAddress(address);
00221     ASSERT(k!=-1);
00222     addresses.erase(addresses.begin()+k);
00223     choosePreferredAddress();
00224 }
00225 
00226 bool IPv6InterfaceData::addrLess(const AddressData& a, const AddressData& b)
00227 {
00228     // This method is used in choosePreferredAddress().
00229     // sort() produces increasing order, so "better" addresses should
00230     // compare as "less", to make them appear first in the array
00231     if (a.tentative!=b.tentative)
00232          return !a.tentative; // tentative=false is better
00233     if (a.address.getScope()!=b.address.getScope())
00234          return a.address.getScope()>b.address.getScope(); // bigger scope is better
00235     return (a.expiryTime==0 && b.expiryTime!=0) || a.expiryTime>b.expiryTime;  // longer expiry time is better
00236 }
00237 
00238 void IPv6InterfaceData::choosePreferredAddress()
00239 {
00240     // do we have addresses?
00241     if (addresses.size()==0)
00242     {
00243         preferredAddr = IPv6Address();
00244         return;
00245     }
00246 
00247     // FIXME shouldn't we stick to the current preferredAddress if its prefLifetime
00248     // hasn't expired yet?
00249 
00250     // FIXME TBD throw out expired addresses! 0 should be treated as infinity
00251 
00252     // sort addresses by scope and expiry time, then pick the first one
00253     std::sort(addresses.begin(), addresses.end(), addrLess);
00254     preferredAddr = addresses[0].address;
00255     preferredAddrExpiryTime = addresses[0].expiryTime;
00256 }
00257 
00258 void IPv6InterfaceData::addAdvPrefix(const AdvPrefix& advPrefix)
00259 {
00260     rtrVars.advPrefixList.push_back(advPrefix);
00261 }
00262 
00263 const IPv6InterfaceData::AdvPrefix& IPv6InterfaceData::getAdvPrefix(int i) const
00264 {
00265     ASSERT(i>=0 && i<(int)rtrVars.advPrefixList.size());
00266     return rtrVars.advPrefixList[i];
00267 }
00268 
00269 void IPv6InterfaceData::setAdvPrefix(int i, const AdvPrefix& advPrefix)
00270 {
00271     ASSERT(i>=0 && i<(int)rtrVars.advPrefixList.size());
00272     ASSERT(rtrVars.advPrefixList[i].prefix == advPrefix.prefix);
00273     ASSERT(rtrVars.advPrefixList[i].prefixLength == advPrefix.prefixLength);
00274     rtrVars.advPrefixList[i] = advPrefix;
00275 }
00276 
00277 void IPv6InterfaceData::removeAdvPrefix(int i)
00278 {
00279     ASSERT(i>=0 && i<(int)rtrVars.advPrefixList.size());
00280     rtrVars.advPrefixList.erase(rtrVars.advPrefixList.begin()+i);
00281 }
00282 
00283 simtime_t IPv6InterfaceData::generateReachableTime(double MIN_RANDOM_FACTOR,
00284     double MAX_RANDOM_FACTOR, uint baseReachableTime)
00285 {
00286     return uniform(MIN_RANDOM_FACTOR, MAX_RANDOM_FACTOR) * baseReachableTime;
00287 }
00288 
00289 simtime_t IPv6InterfaceData::generateReachableTime()
00290 {
00291     return uniform(_getMinRandomFactor(), _getMaxRandomFactor()) * getBaseReachableTime();
00292 }
00293 
00294