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