Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "bgp/inet/inet_route.h" 6 : 7 : #include <algorithm> 8 : 9 : #include "bgp/inet/inet_table.h" 10 : 11 : using std::copy; 12 : using std::string; 13 : using std::vector; 14 : 15 6871 : int Ip4Prefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix, 16 : Ip4Prefix *prefix) { 17 6871 : if (proto_prefix.prefix.size() > Address::kMaxV4Bytes) 18 1 : return -1; 19 6869 : prefix->prefixlen_ = proto_prefix.prefixlen; 20 6869 : Ip4Address::bytes_type bt = { { 0 } }; 21 6869 : copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin()); 22 6869 : prefix->ip4_addr_ = Ip4Address(bt); 23 : 24 6869 : return 0; 25 : } 26 : 27 6844 : int Ip4Prefix::FromProtoPrefix(BgpServer *server, 28 : const BgpProtoPrefix &proto_prefix, 29 : const BgpAttr *attr, 30 : const Address::Family family, 31 : Ip4Prefix *prefix, 32 : BgpAttrPtr *new_attr, uint32_t *label, 33 : uint32_t *l3_label) { 34 6844 : if (family == Address::INET) { 35 6838 : return FromProtoPrefix(proto_prefix, prefix); 36 : } 37 6 : size_t nlri_size = proto_prefix.prefix.size(); 38 6 : size_t expected_min_nlri_size = 39 : BgpProtoPrefix::kLabelSize; 40 : 41 6 : if (nlri_size < expected_min_nlri_size) 42 0 : return -1; 43 6 : if (nlri_size > expected_min_nlri_size + Address::kMaxV4Bytes) 44 0 : return -1; 45 : 46 6 : size_t label_offset = 0; 47 6 : *label = proto_prefix.ReadLabel(label_offset); 48 6 : size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize; 49 6 : prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8; 50 6 : Ip4Address::bytes_type bt = { { 0 } }; 51 6 : copy(proto_prefix.prefix.begin() + prefix_offset, 52 : proto_prefix.prefix.end(), bt.begin()); 53 6 : prefix->ip4_addr_ = Ip4Address(bt); 54 : 55 6 : return 0; 56 : } 57 : 58 : 59 : 60 912717 : string Ip4Prefix::ToString() const { 61 912717 : string repr(ip4_addr().to_string()); 62 : char strplen[4]; 63 912804 : snprintf(strplen, sizeof(strplen), "/%d", prefixlen()); 64 912787 : repr.append(strplen); 65 1825962 : return repr; 66 0 : } 67 : 68 6030866 : int Ip4Prefix::CompareTo(const Ip4Prefix &rhs) const { 69 6030866 : if (ip4_addr_ < rhs.ip4_addr_) { 70 2967685 : return -1; 71 : } 72 3062445 : if (ip4_addr_ > rhs.ip4_addr_) { 73 2077051 : return 1; 74 : } 75 987203 : if (prefixlen_ < rhs.prefixlen_) { 76 135 : return -1; 77 : } 78 987068 : if (prefixlen_ > rhs.prefixlen_) { 79 78 : return 1; 80 : } 81 986990 : return 0; 82 : } 83 : 84 168824 : Ip4Prefix Ip4Prefix::FromString(const string &str, 85 : boost::system::error_code *errorp) { 86 168824 : Ip4Prefix prefix; 87 168822 : boost::system::error_code pfxerr = Ip4SubnetParse(str, &prefix.ip4_addr_, 88 : &prefix.prefixlen_); 89 168822 : if (errorp != NULL) { 90 100725 : *errorp = pfxerr; 91 : } 92 337644 : return prefix; 93 : } 94 : 95 : // Check whether 'this' is more specific than rhs. 96 26602 : bool Ip4Prefix::IsMoreSpecific(const Ip4Prefix &rhs) const { 97 : // My prefixlen must be longer in order to be more specific. 98 26602 : if (prefixlen_ < rhs.prefixlen()) return false; 99 : 100 26371 : uint32_t mask = 0; 101 26371 : if (rhs.prefixlen()) 102 26320 : mask = ((uint32_t) ~0) << (Address::kMaxV4PrefixLen - rhs.prefixlen()); 103 26365 : return (ip4_addr_.to_ulong() & mask) == 104 26366 : (rhs.ip4_addr().to_ulong() & mask); 105 : } 106 : 107 890697 : InetRoute::InetRoute(const Ip4Prefix &prefix) 108 890600 : : prefix_(prefix), 109 890697 : prefix_str_(prefix.ToString()) { 110 890779 : } 111 : 112 5976423 : int InetRoute::CompareTo(const Route &rhs) const { 113 5976423 : const InetRoute &rt_other = static_cast<const InetRoute &>(rhs); 114 5976423 : return prefix_.CompareTo(rt_other.prefix_); 115 : } 116 : 117 : // Check whether 'this' is more specific than rhs. 118 1470 : bool InetRoute::IsMoreSpecific(const string &match) const { 119 1470 : boost::system::error_code ec; 120 : 121 1470 : Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec); 122 1468 : if (!ec) { 123 1459 : return GetPrefix().IsMoreSpecific(prefix); 124 : } 125 : 126 9 : return false; 127 : } 128 : 129 : // Check whether 'this' is less specific than rhs. 130 81 : bool InetRoute::IsLessSpecific(const string &match) const { 131 81 : boost::system::error_code ec; 132 : 133 81 : Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec); 134 81 : if (!ec) { 135 81 : return prefix.IsMoreSpecific(GetPrefix()); 136 : } 137 : 138 0 : return false; 139 : } 140 : 141 202660 : DBEntryBase::KeyPtr InetRoute::GetDBRequestKey() const { 142 202660 : InetTable::RequestKey *key = new InetTable::RequestKey(prefix_, NULL); 143 202583 : return KeyPtr(key); 144 : } 145 : 146 2 : void InetRoute::SetKey(const DBRequestKey *reqkey) { 147 2 : const InetTable::RequestKey *key = 148 : static_cast<const InetTable::RequestKey *>(reqkey); 149 2 : prefix_ = key->prefix; 150 2 : } 151 : 152 7896 : void InetRoute::BuildProtoPrefix(BgpProtoPrefix *prefix, 153 : const BgpAttr *attr, 154 : const uint32_t label, 155 : uint32_t l3_label) const { 156 : size_t prefix_size; 157 7896 : prefix->prefix.clear(); 158 7896 : if (label) { // Labeled Unicast 159 3 : prefix_size = (prefix_.prefixlen() + 7) / 8; 160 3 : size_t nlri_size = BgpProtoPrefix::kLabelSize + prefix_size; 161 3 : prefix->prefix.resize(nlri_size, 0); 162 3 : size_t label_offset = 0; 163 3 : prefix->WriteLabel(label_offset, label); 164 3 : size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize; 165 3 : prefix->prefixlen = prefix_offset * 8 + prefix_.prefixlen(); 166 3 : const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes(); 167 3 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size, 168 6 : prefix->prefix.begin() + prefix_offset); 169 : } else { 170 7893 : prefix->prefixlen = prefix_.prefixlen(); 171 7893 : const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes(); 172 7893 : prefix_size = (prefix->prefixlen + 7) / 8; 173 7893 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size, 174 7893 : back_inserter(prefix->prefix)); 175 : } 176 7895 : } 177 : 178 4527 : void InetRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh, 179 : IpAddress nexthop) const { 180 4527 : nh.resize(Address::kMaxV4Bytes); 181 4527 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes(); 182 4527 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin()); 183 4527 : }