Line data Source code
1 : /* 2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "base/misc_utils.h" 6 : #include "base/string_util.h" 7 : #include "bgp/inet6/inet6_route.h" 8 : #include "bgp/inet6/inet6_table.h" 9 : 10 : using boost::system::error_code; 11 : using std::copy; 12 : using std::string; 13 : using std::vector; 14 : 15 5888 : int Inet6Prefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix, 16 : Inet6Prefix *prefix) { 17 5888 : if (proto_prefix.prefix.size() > Address::kMaxV6Bytes) 18 0 : return -1; 19 5888 : prefix->prefixlen_ = proto_prefix.prefixlen; 20 5888 : Ip6Address::bytes_type bt = { { 0 } }; 21 5888 : copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin()); 22 5888 : prefix->ip6_addr_ = Ip6Address(bt); 23 : 24 5888 : return 0; 25 : } 26 : 27 5886 : int Inet6Prefix::FromProtoPrefix(BgpServer *server, 28 : const BgpProtoPrefix &proto_prefix, 29 : const BgpAttr *attr, 30 : const Address::Family family, 31 : Inet6Prefix *prefix, BgpAttrPtr *new_attr, 32 : uint32_t *label, uint32_t *l3_label) { 33 5886 : return FromProtoPrefix(proto_prefix, prefix); 34 : } 35 : 36 711088 : string Inet6Prefix::ToString() const { 37 711088 : string repr(ip6_addr().to_string()); 38 711192 : repr.append("/" + integerToString(prefixlen())); 39 711264 : return repr; 40 0 : } 41 : 42 5419511 : int Inet6Prefix::CompareTo(const Inet6Prefix &rhs) const { 43 5419511 : if (ip6_addr_ < rhs.ip6_addr_) { 44 2691379 : return -1; 45 : } 46 2727932 : if (ip6_addr_ > rhs.ip6_addr_) { 47 1887885 : return 1; 48 : } 49 842261 : if (prefixlen_ < rhs.prefixlen_) { 50 102 : return -1; 51 : } 52 842159 : if (prefixlen_ > rhs.prefixlen_) { 53 55 : return 1; 54 : } 55 842104 : return 0; 56 : } 57 : 58 59833 : Inet6Prefix Inet6Prefix::FromString(const string &str, error_code *error) { 59 59833 : Inet6Prefix prefix; 60 59832 : error_code pfxerr = Inet6SubnetParse(str, &prefix.ip6_addr_, 61 : &prefix.prefixlen_); 62 59833 : if (error != NULL) { 63 52660 : *error = pfxerr; 64 : } 65 119666 : return prefix; 66 : } 67 : 68 : // Check whether 'this' is more specific than rhs. 69 20680 : bool Inet6Prefix::IsMoreSpecific(const Inet6Prefix &rhs) const { 70 : // My prefixlen must be longer in order to be more specific. 71 20680 : if (prefixlen_ < rhs.prefixlen()) { 72 87 : return false; 73 : } 74 20590 : Inet6Prefix mask = Inet6Masks::PrefixlenToMask(rhs.prefixlen()); 75 20588 : Inet6Prefix left = operator&(mask); 76 20617 : Inet6Prefix right = rhs.operator&(mask); 77 : 78 20617 : return (left.ToBytes() == right.ToBytes()); 79 : } 80 : 81 41191 : Inet6Prefix Inet6Prefix::operator&(const Inet6Prefix& right) const { 82 : Ip6Address::bytes_type addr_bytes; 83 41191 : ARRAYBYTES_FILL(addr_bytes,0); 84 : 85 41162 : Ip6Address::bytes_type lhs = ToBytes(); 86 41150 : Ip6Address::bytes_type rhs = right.ToBytes(); 87 : 88 41198 : int plen = (prefixlen_ <= right.prefixlen_ ? prefixlen() : right.prefixlen()); 89 : 90 697258 : for (size_t i = 0; i < sizeof(Ip6Address::bytes_type); ++i) { 91 656134 : addr_bytes[i] = lhs[i] & rhs[i]; 92 : } 93 : 94 41124 : return Inet6Prefix(Ip6Address(addr_bytes), plen); 95 : } 96 : 97 : // Routines for class Inet6Route 98 : 99 694499 : Inet6Route::Inet6Route(const Inet6Prefix &prefix) 100 694456 : : prefix_(prefix), 101 694499 : prefix_str_(prefix.ToString()) { 102 694588 : } 103 : 104 5376431 : int Inet6Route::CompareTo(const Route &rhs) const { 105 5376431 : const Inet6Route &rt_other = static_cast<const Inet6Route &>(rhs); 106 5376431 : return prefix_.CompareTo(rt_other.prefix_); 107 : } 108 : 109 : // Check whether 'this' is more specific than rhs. 110 5 : bool Inet6Route::IsMoreSpecific(const string &match) const { 111 5 : error_code ec; 112 : 113 5 : Inet6Prefix prefix = Inet6Prefix::FromString(match, &ec); 114 5 : if (!ec) { 115 5 : return GetPrefix().IsMoreSpecific(prefix); 116 : } 117 : 118 0 : return false; 119 : } 120 : 121 : // Check whether 'this' is less specific than rhs. 122 3 : bool Inet6Route::IsLessSpecific(const string &match) const { 123 3 : error_code ec; 124 : 125 3 : Inet6Prefix prefix = Inet6Prefix::FromString(match, &ec); 126 3 : if (!ec) { 127 3 : return prefix.IsMoreSpecific(GetPrefix()); 128 : } 129 : 130 0 : return false; 131 : } 132 : 133 172639 : DBEntryBase::KeyPtr Inet6Route::GetDBRequestKey() const { 134 172639 : Inet6Table::RequestKey *key = new Inet6Table::RequestKey(prefix_, NULL); 135 172632 : return KeyPtr(key); 136 : } 137 : 138 1 : void Inet6Route::SetKey(const DBRequestKey *reqkey) { 139 1 : const Inet6Table::RequestKey *key = 140 : static_cast<const Inet6Table::RequestKey *>(reqkey); 141 1 : prefix_ = key->prefix; 142 1 : } 143 : 144 5221 : void Inet6Route::BuildProtoPrefix(BgpProtoPrefix *prefix, 145 : const BgpAttr *attr, 146 : uint32_t label, 147 : uint32_t l3_label) const { 148 5221 : prefix->prefixlen = prefix_.prefixlen(); 149 5221 : prefix->prefix.clear(); 150 5221 : const Ip6Address::bytes_type &addr_bytes = prefix_.ip6_addr().to_bytes(); 151 5221 : int num_bytes = (prefix->prefixlen + 7) / 8; 152 5221 : copy(addr_bytes.begin(), addr_bytes.begin() + num_bytes, 153 5221 : back_inserter(prefix->prefix)); 154 5221 : } 155 : 156 : // 157 : // Fill in the vector based on the supplied nexthop. 158 : // 159 2623 : void Inet6Route::BuildBgpProtoNextHop(vector<uint8_t> &nh, 160 : IpAddress nexthop) const { 161 2623 : nh.resize(Address::kMaxV6Bytes); 162 2624 : Ip6Address address; 163 2624 : if (nexthop.is_v4()) { 164 750 : address = Ip6Address::v4_mapped(nexthop.to_v4()); 165 : } else { 166 1874 : address = nexthop.to_v6(); 167 : } 168 : 169 2624 : const Ip6Address::bytes_type &addr_bytes = address.to_bytes(); 170 2624 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin()); 171 2623 : } 172 : 173 : // Routines for class Inet6Masks 174 : 175 : // Definitions of the static members 176 : bool Inet6Masks::initialized_ = false; 177 : vector<Inet6Prefix> Inet6Masks::masks_; 178 : 179 20718 : const Inet6Prefix& Inet6Masks::PrefixlenToMask(uint8_t prefix_len) { 180 20718 : assert(prefix_len <= Inet6Prefix::kMaxV6PrefixLen); 181 20718 : return masks_.at(prefix_len); 182 : } 183 : 184 159 : void Inet6Masks::Init() { 185 159 : assert(initialized_ == false); 186 20670 : for (int i = 0; i <= Inet6Prefix::kMaxV6PrefixLen; ++i) { 187 20511 : masks_.push_back(CalculateMaskFromPrefixlen(i)); 188 : } 189 159 : initialized_ = true; 190 159 : } 191 : 192 0 : void Inet6Masks::Clear() { 193 0 : masks_.clear(); 194 0 : initialized_ = false; 195 0 : } 196 : 197 20511 : Inet6Prefix Inet6Masks::CalculateMaskFromPrefixlen(int prefixlen) { 198 20511 : int num_bytes = prefixlen / 8; 199 20511 : int num_bits = prefixlen % 8; 200 : 201 : Ip6Address::bytes_type addr_bytes; 202 20511 : ARRAYBYTES_FILL(addr_bytes,0); 203 : 204 175695 : for (int i = 0; i < num_bytes; ++i) { 205 155184 : addr_bytes[i] = 0xff; 206 : } 207 20511 : if (num_bits) { 208 17808 : uint8_t hex_val = 0xff << (8 - num_bits); 209 17808 : addr_bytes[num_bytes] = hex_val; 210 : } 211 20511 : return Inet6Prefix(Ip6Address(addr_bytes), prefixlen); 212 : } 213 : 214 159 : static void Inet6InitRoutines() { 215 159 : Inet6Masks::Init(); 216 159 : } 217 : MODULE_INITIALIZER(Inet6InitRoutines);