41#ifndef _DWMIPV4ROUTES_HH_
42#define _DWMIPV4ROUTES_HH_
47#include <unordered_map>
60 struct OurIpv4AddressHash
125 template <
typename _valueT>
130 OurIpv4AddressHash> _RepSubType;
131 typedef typename _RepSubType::const_iterator const_iterator;
139 for (uint8_t i = 0; i < 33; ++i) {
140 _hashMaps[i].max_load_factor(.08);
149 for (uint8_t i = 0; i < 33; ++i)
150 _hashMaps[i].clear();
160 for (uint8_t i = 0; i < 33; ++i) {
161 if (! _hashMaps[i].empty()) {
177 typename _RepSubType::iterator iter =
179 if (iter == _hashMaps[prefix.
MaskLength()].end()) {
191 for (uint8_t i = 0; i < 33; ++i) {
192 if (! routes._hashMaps[i].empty()) {
193 for (
const auto & entry : routes._hashMaps[i]) {
194 _hashMaps[i][entry.first] = entry.second;
216 typename _RepSubType::iterator iter =
218 if (iter != _hashMaps[prefix.
MaskLength()].end()) {
233 if (! _hashMaps[prefix.
MaskLength()].empty()) {
234 typename _RepSubType::const_iterator iter =
236 if (iter != _hashMaps[prefix.
MaskLength()].end()) {
237 match = iter->second;
247 void FindInSubMap(
const _RepSubType & subMap,
Ipv4Address ipAddr,
248 std::pair<bool,_valueT> & result)
const
250 auto iter = subMap.find(ipAddr);
251 if (iter != subMap.end()) {
253 result.second = iter->second;
261 bool NewFindLongest(
const Ipv4Address & ipAddr,
262 std::pair<Ipv4Prefix,_valueT> & match)
const
264 using std::map, std::pair, std::thread;
266 map<uint8_t,pair<bool,_valueT>> results;
267 std::map<uint8_t,thread> threads;
268 for (
int i = 32; i >= 0; --i) {
269 if (! _hashMaps[i].empty()) {
270 results[i] = {
false,_valueT()};
271 Ipv4Prefix pfx(ipAddr, i);
272 threads[i] = thread(&Ipv4Routes::FindInSubMap,
this,
273 std::ref(_hashMaps[i]), pfx.Network(),
274 std::ref(results[i]));
277 for (
auto it = threads.rbegin(); it != threads.rend(); ++it) {
279 if (results[it->first].first) {
281 match.first = Ipv4Prefix(ipAddr, it->first);
282 match.second = results[it->first].second;
294 std::pair<Ipv4Prefix,_valueT> & match)
const
299 typename _RepSubType::const_iterator iter;
300 for (int8_t i = 32; i >= 0; --i) {
301 if (_hashMaps[i].empty())
304 iter = _hashMaps[i].find(lp.
Network());
305 if (iter != _hashMaps[i].end()) {
307 match.second = iter->second;
325 std::pair<Ipv4Prefix, const _valueT *> & match)
const
329 typename _RepSubType::const_iterator iter;
330 for (int8_t i = 32; i >= 0; --i) {
331 if (_hashMaps[i].empty())
334 iter = _hashMaps[i].find(lp.
Network());
335 if (iter != _hashMaps[i].end()) {
337 match.second = &(iter->second);
351 std::vector<std::pair<Ipv4Prefix,_valueT> > & matches)
const
353 if (! matches.empty())
356 typename _RepSubType::const_iterator iter;
358 for (int8_t i = 32; i >= 0; --i) {
359 if (_hashMaps[i].empty())
362 iter = _hashMaps[i].find(prefix.
Network());
363 if (iter != _hashMaps[i].end()) {
364 std::pair<Ipv4Prefix,_valueT> match(prefix, iter->second);
365 matches.push_back(match);
368 return(! matches.empty());
374 void MaxLoadFactor(
float loadFactor)
376 for (int8_t i = 32; i >= 0; --i) {
377 _hashMaps[i].max_load_factor(loadFactor);
389 for (int8_t i = 32; i >= 0; --i) {
390 if (_hashMaps[i] != r._hashMaps[i])
403 return(! (*
this == r));
412 for (uint8_t i = 0; i < 33; ++i)
413 rc += _hashMaps[i].size();
420 void HashSizes(std::vector<std::pair<uint8_t, uint32_t> > & sizes)
const
424 for (uint8_t i = 0; i < 33; ++i) {
425 if (! _hashMaps[i].empty()) {
426 sizes.push_back(std::pair<uint8_t,uint32_t>(i,_hashMaps[i].size()));
435 uint64_t StreamedLength()
const
443 std::istream &
Read(std::istream & is)
451 std::ostream &
Write(std::ostream & os)
const
538 template <
typename BinaryPredicate>
542 for (uint8_t maskLen = 32; maskLen > 0; --maskLen) {
543 auto & hm = this->_hashMaps[maskLen];
544 auto hmi = hm.begin();
545 while (hmi != hm.end()) {
550 std::pair<bool,Ipv4Prefix> combpfx = pfx.
Combine(nextpfx);
552 auto nextit = hm.find(nextpfx.
Network());
553 if (nextit != hm.end()) {
554 if (pred(hmi->second, nextit->second)) {
556 _hashMaps[maskLen-1][combpfx.second.Network()] = hmi->second;
569 for (uint8_t maskLen = 32; maskLen > 0; --maskLen) {
570 auto & hm = this->_hashMaps[maskLen];
571 auto hmi = hm.begin();
572 while (hmi != hm.end()) {
573 if (HaveWiderMatch(hmi->first, maskLen, hmi->second, pred)) {
589 return Coalesce(std::equal_to<_valueT>());
595 void GetAllKeys(std::vector<Ipv4Prefix> & keys)
const
597 keys.resize(this->
Size());
598 if (! keys.empty()) {
600 for (uint8_t hashNum = 0; hashNum < 33; ++hashNum) {
601 for (
const auto & entry : this->_hashMaps[hashNum]) {
602 keys[pfx] = Ipv4Prefix(entry.first, hashNum);
613 void SortByKey(std::vector<std::pair<Ipv4Prefix,_valueT>> & target,
614 bool ascending =
true)
const
616 if (! target.empty())
618 if (! this->_hashMaps.empty()) {
619 target.resize(this->
Size());
620 auto iter = this->_hashMaps.begin();
622 for (uint8_t hashNum = 0; hashNum < 33; ++hashNum) {
623 if (! this->_hashMaps[hashNum].empty()) {
624 auto hiter = this->_hashMaps[hashNum].begin();
625 for ( ; hiter != iter->end(); ++hiter) {
626 target[pfx].first = Ipv4Prefix(hiter->first, hashNum);
627 target[pfx].second = hiter->second;
632 if (! target.empty()) {
634 std::sort(target.begin(), target.end(), KeyLess());
637 std::sort(target.begin(), target.end(), KeyGreater());
652 void SortByValue(std::vector<std::pair<Ipv4Prefix,_valueT> > & target)
654 if (! target.empty())
656 if (! this->_hashMaps.empty()) {
657 target.resize(this->
Size());
658 auto iter = this->_hashMaps.begin();
660 for (uint8_t hashNum = 0; hashNum < 33; ++hashNum) {
661 if (! this->_hashMaps[hashNum].empty()) {
662 auto hiter = this->_hashMaps[hashNum].begin();
663 for ( ; hiter != iter->end(); ++hiter) {
664 target[pfx].first =
Ipv4Prefix(hiter->first, hashNum);
665 target[pfx].second = hiter->second;
670 if (! target.empty())
671 std::sort(target.begin(), target.end(),
672 [] (
const auto & e1,
const auto & e2)
673 { return (e1.second > e2.second); });
686 for (int8_t hashNum = 32; hashNum > 1; --hashNum) {
687 typename _RepSubType::const_iterator hiter =
688 _hashMaps[hashNum].begin();
689 for ( ; hiter != _hashMaps[hashNum].end(); ++hiter) {
690 bool foundWider =
false;
691 for (int8_t widerHash = hashNum - 1; widerHash > 0; --widerHash) {
693 if (_hashMaps[widerHash].find(widerPfx.
Network())
694 != _hashMaps[widerHash].end()) {
701 rc += ((uint32_t)1 << (32 - hashNum));
711 bool operator () (
const std::pair<Ipv4Prefix,_valueT> & e1,
712 const std::pair<Ipv4Prefix,_valueT> & e2)
const
714 return(e1.first > e2.first);
721 bool operator () (
const std::pair<Ipv4Prefix,_valueT> & e1,
722 const std::pair<Ipv4Prefix,_valueT> & e2)
const
724 return(e1.first < e2.first);
732 bool operator () (
const std::pair<Ipv4Prefix,_valueT> & e1,
733 const std::pair<Ipv4Prefix,_valueT> & e2)
const
735 return(e1.second > e2.second);
743 const std::array<_RepSubType,33> &
HashMaps()
const
749 std::array<_RepSubType,33> _hashMaps;
751 template <
typename BinaryPredicate>
752 bool HaveWiderMatch(
const Ipv4Address & addr, uint8_t maskLen,
753 const _valueT & val, BinaryPredicate pred)
const
757 for (int8_t wml = maskLen - 1; wml > 0; --wml) {
759 auto iter = _hashMaps[wml].find(pfx.Network());
760 if (iter != _hashMaps[wml].end()) {
761 if (pred(iter->second, val)) {
Dwm::BZ2IO class declaration.
Dwm::DescriptorIO class declaration.
Dwm::FileIO class declaration.
Dwm::GZIO class definition.
Dwm::IOUtils class declaration and implementation.
Dwm::Ipv4Prefix class definition.
A configure target for dealing with OS differences.
Dwm::StreamIO class declaration.
static int BZRead(BZFILE *bzf, char &c)
Reads from bzf.
static int BZWrite(BZFILE *bzf, char c)
Writes c to bzf.
static ssize_t Write(int fd, char c)
Writes c to fd.
static ssize_t Read(int fd, char &c)
Reads c from fd.
static size_t Write(FILE *f, char c)
Writes c to f.
static size_t Read(FILE *f, char &c)
Reads c from f.
static int Write(gzFile gzf, char c)
Writes c to gzf.
static int Read(gzFile gzf, char &c)
Reads from gzf.
static uint64_t StreamedLength(char c)
Returns the number of bytes that would be written if we called Write() for a char.
Definition DwmIOUtils.hh:85
This class encapsulates an IPv4 address.
Definition DwmIpv4Address.hh:63
ipv4addr_t Raw() const
Returns an ipv4addr_t representation (32-bit value in network byte order).
Definition DwmIpv4Address.hh:86
This class encapsulates an IPv4 address and netmask.
Definition DwmIpv4Prefix.hh:59
std::pair< bool, Ipv4Prefix > Combine(const Ipv4Prefix &prefix) const
If the given prefix can be combined with this prefix to form a single prefix, returns [true,...
uint8_t MaskLength() const
Returns the length of the netmask (number of significant bits).
Definition DwmIpv4Prefix.hh:137
Ipv4Address Network() const
Returns the network portion of the prefix.
Definition DwmIpv4Prefix.hh:116
This template class provides an associative container keyed by IPv4 addresses, with longest-match sea...
Definition DwmIpv4Routes.hh:127
bool Find(const Ipv4Address &ipAddr, std::vector< std::pair< Ipv4Prefix, _valueT > > &matches) const
Finds all matches for ipAddr.
Definition DwmIpv4Routes.hh:350
bool FindLongest(const Ipv4Address &ipAddr, std::pair< Ipv4Prefix, _valueT > &match) const
Finds the longest match for ipAddr.
Definition DwmIpv4Routes.hh:293
int Read(gzFile gzf)
Reads the routes from a gzFile.
Definition DwmIpv4Routes.hh:496
bool Find(const Ipv4Prefix &prefix, _valueT &match) const
Find the entry for the given prefix.
Definition DwmIpv4Routes.hh:230
Ipv4Routes()
Constructor.
Definition DwmIpv4Routes.hh:136
std::ostream & Write(std::ostream &os) const
Writes the routes to an ostream. Returns the ostream.
Definition DwmIpv4Routes.hh:451
bool operator==(const Ipv4Routes< _valueT > &r) const
operator == It's unlikely you'd ever need to use this, and it's expensive.
Definition DwmIpv4Routes.hh:387
bool Delete(const Ipv4Prefix &prefix)
Deletes the entry for prefix.
Definition DwmIpv4Routes.hh:213
void Coalesce(BinaryPredicate pred)
Combines adjacent prefixes that can be combined (same value and prefixes can be represented by a pref...
Definition DwmIpv4Routes.hh:539
size_t Write(FILE *f) const
Writes the routes to a FILE pointer.
Definition DwmIpv4Routes.hh:469
void SortByValue(std::vector< std::pair< Ipv4Prefix, _valueT > > &target)
Sorts the contained pair<Ipv4Prefix,_valueT> values into a vector, in descending order by the value s...
Definition DwmIpv4Routes.hh:652
std::istream & Read(std::istream &is)
Reads the routes from an istream. Returns the istream.
Definition DwmIpv4Routes.hh:443
ssize_t Write(int fd) const
Writes the routes to a file descriptor.
Definition DwmIpv4Routes.hh:487
int BZRead(BZFILE *bzf)
Reads the routes from a BZFILE pointer.
Definition DwmIpv4Routes.hh:514
void Clear()
Clears all entries.
Definition DwmIpv4Routes.hh:147
bool FindLongest(const Ipv4Address &ipAddr, std::pair< Ipv4Prefix, const _valueT * > &match) const
Finds the longest match for ipAddr.
Definition DwmIpv4Routes.hh:324
size_t Read(FILE *f)
Reades the routes from a FILE pointer.
Definition DwmIpv4Routes.hh:460
const std::array< _RepSubType, 33 > & HashMaps() const
Returns a const reference to the contained hash maps.
Definition DwmIpv4Routes.hh:743
int BZWrite(BZFILE *bzf) const
Writes the routes to a BZFILE pointer.
Definition DwmIpv4Routes.hh:523
_valueT & operator[](const Ipv4Prefix &prefix)
operator [] works like you would expect from an STL map.
Definition DwmIpv4Routes.hh:204
int Write(gzFile gzf) const
Writes the routes to a gzFile.
Definition DwmIpv4Routes.hh:505
uint32_t Size() const
Returns the number of routes.
Definition DwmIpv4Routes.hh:409
bool Empty() const
Returns true if there are no entries.
Definition DwmIpv4Routes.hh:157
void Add(const Ipv4Routes< _valueT > &routes)
Bulk add all routes. Note this will overwrite existing routes.
Definition DwmIpv4Routes.hh:189
bool Add(const Ipv4Prefix &prefix, const _valueT &value)
Adds an entry.
Definition DwmIpv4Routes.hh:173
uint32_t AddressesCovered() const
Returns the number of addresses covered by the contained prefixes, not including 0/0.
Definition DwmIpv4Routes.hh:683
bool operator!=(const Ipv4Routes< _valueT > &r) const
operator != It's unlikely you'd ever need to use this, and it's expensive.
Definition DwmIpv4Routes.hh:401
ssize_t Read(int fd)
Reads the routes from a file descriptor.
Definition DwmIpv4Routes.hh:478
static std::istream & Read(std::istream &is, char &c)
Reads c from is. Returns is.
static std::ostream & Write(std::ostream &os, char c)
Writes c to os. Returns os.