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