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 6907 : int Ip4Prefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix, 16 : Ip4Prefix *prefix) { 17 6907 : if (proto_prefix.prefix.size() > Address::kMaxV4Bytes) 18 1 : return -1; 19 6906 : prefix->prefixlen_ = proto_prefix.prefixlen; 20 6906 : Ip4Address::bytes_type bt = { { 0 } }; 21 6906 : copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin()); 22 6906 : prefix->ip4_addr_ = Ip4Address(bt); 23 : 24 6906 : return 0; 25 : } 26 : 27 6882 : 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 6882 : if (family == Address::INET) { 35 6874 : return FromProtoPrefix(proto_prefix, prefix); 36 : } 37 8 : size_t nlri_size = proto_prefix.prefix.size(); 38 8 : size_t expected_min_nlri_size = 39 : BgpProtoPrefix::kLabelSize; 40 : 41 8 : if (nlri_size < expected_min_nlri_size) 42 0 : return -1; 43 8 : if (nlri_size > expected_min_nlri_size + Address::kMaxV4Bytes) 44 0 : return -1; 45 : 46 8 : size_t label_offset = 0; 47 8 : *label = proto_prefix.ReadLabel(label_offset); 48 8 : size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize; 49 8 : prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8; 50 8 : Ip4Address::bytes_type bt = { { 0 } }; 51 8 : copy(proto_prefix.prefix.begin() + prefix_offset, 52 : proto_prefix.prefix.end(), bt.begin()); 53 8 : prefix->ip4_addr_ = Ip4Address(bt); 54 : 55 8 : return 0; 56 : } 57 : 58 : 59 : 60 913711 : string Ip4Prefix::ToString() const { 61 913711 : string repr(ip4_addr().to_string()); 62 : char strplen[4]; 63 913847 : snprintf(strplen, sizeof(strplen), "/%d", prefixlen()); 64 913831 : repr.append(strplen); 65 1827756 : return repr; 66 0 : } 67 : 68 6083480 : int Ip4Prefix::CompareTo(const Ip4Prefix &rhs) const { 69 6083480 : if (ip4_addr_ < rhs.ip4_addr_) { 70 2998278 : return -1; 71 : } 72 3084493 : if (ip4_addr_ > rhs.ip4_addr_) { 73 2103690 : return 1; 74 : } 75 982233 : if (prefixlen_ < rhs.prefixlen_) { 76 136 : return -1; 77 : } 78 982097 : if (prefixlen_ > rhs.prefixlen_) { 79 81 : return 1; 80 : } 81 982016 : return 0; 82 : } 83 : 84 169128 : Ip4Prefix Ip4Prefix::FromString(const string &str, 85 : boost::system::error_code *errorp) { 86 169128 : Ip4Prefix prefix; 87 169126 : boost::system::error_code pfxerr = Ip4SubnetParse(str, &prefix.ip4_addr_, 88 : &prefix.prefixlen_); 89 169125 : if (errorp != NULL) { 90 101021 : *errorp = pfxerr; 91 : } 92 338250 : return prefix; 93 : } 94 : 95 : // Check whether 'this' is more specific than rhs. 96 26698 : bool Ip4Prefix::IsMoreSpecific(const Ip4Prefix &rhs) const { 97 : // My prefixlen must be longer in order to be more specific. 98 26698 : if (prefixlen_ < rhs.prefixlen()) return false; 99 : 100 26444 : uint32_t mask = 0; 101 26444 : if (rhs.prefixlen()) 102 26396 : mask = ((uint32_t) ~0) << (Address::kMaxV4PrefixLen - rhs.prefixlen()); 103 26443 : return (ip4_addr_.to_ulong() & mask) == 104 26441 : (rhs.ip4_addr().to_ulong() & mask); 105 : } 106 : 107 891625 : InetRoute::InetRoute(const Ip4Prefix &prefix) 108 891568 : : prefix_(prefix), 109 891625 : prefix_str_(prefix.ToString()) { 110 891692 : } 111 : 112 6029852 : int InetRoute::CompareTo(const Route &rhs) const { 113 6029852 : const InetRoute &rt_other = static_cast<const InetRoute &>(rhs); 114 6029852 : return prefix_.CompareTo(rt_other.prefix_); 115 : } 116 : 117 : // Check whether 'this' is more specific than rhs. 118 1472 : bool InetRoute::IsMoreSpecific(const string &match) const { 119 1472 : boost::system::error_code ec; 120 : 121 1472 : Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec); 122 1469 : if (!ec) { 123 1460 : 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 208731 : DBEntryBase::KeyPtr InetRoute::GetDBRequestKey() const { 142 208731 : InetTable::RequestKey *key = new InetTable::RequestKey(prefix_, NULL); 143 208681 : 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 7914 : 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 7914 : prefix->prefix.clear(); 158 7914 : if (label) { // Labeled Unicast 159 4 : prefix_size = (prefix_.prefixlen() + 7) / 8; 160 4 : size_t nlri_size = BgpProtoPrefix::kLabelSize + prefix_size; 161 4 : prefix->prefix.resize(nlri_size, 0); 162 4 : size_t label_offset = 0; 163 4 : prefix->WriteLabel(label_offset, label); 164 4 : size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize; 165 4 : prefix->prefixlen = prefix_offset * 8 + prefix_.prefixlen(); 166 4 : const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes(); 167 4 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size, 168 8 : prefix->prefix.begin() + prefix_offset); 169 : } else { 170 7910 : prefix->prefixlen = prefix_.prefixlen(); 171 7910 : const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes(); 172 7910 : prefix_size = (prefix->prefixlen + 7) / 8; 173 7910 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size, 174 7910 : back_inserter(prefix->prefix)); 175 : } 176 7916 : } 177 : 178 4684 : void InetRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh, 179 : IpAddress nexthop) const { 180 4684 : nh.resize(Address::kMaxV4Bytes); 181 4684 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes(); 182 4684 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin()); 183 4684 : }