Line data Source code
1 : /*
2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/inet6vpn/inet6vpn_route.h"
6 :
7 : #include <algorithm>
8 :
9 : #include "bgp/inet6vpn/inet6vpn_table.h"
10 : #include "bgp/inet6/inet6_route.h"
11 :
12 : using std::copy;
13 : using std::string;
14 : using std::vector;
15 :
16 64894 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
17 64894 : }
18 :
19 49683 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
20 : Inet6VpnPrefix *prefix, uint32_t *label) {
21 49683 : size_t nlri_size = proto_prefix.prefix.size();
22 49683 : size_t expected_min_nlri_size =
23 49683 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
24 :
25 49683 : if (nlri_size < expected_min_nlri_size)
26 1 : return -1;
27 49682 : if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
28 1 : return -1;
29 :
30 49681 : size_t label_offset = 0;
31 49681 : *label = proto_prefix.ReadLabel(label_offset);
32 49681 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
33 49681 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
34 :
35 49681 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
36 49681 : prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
37 49681 : Ip6Address::bytes_type bt = { { 0 } };
38 49681 : copy(proto_prefix.prefix.begin() + prefix_offset,
39 : proto_prefix.prefix.end(), bt.begin());
40 49681 : prefix->addr_ = Ip6Address(bt);
41 :
42 49680 : return 0;
43 : }
44 :
45 49678 : int Inet6VpnPrefix::FromProtoPrefix(BgpServer *server,
46 : const BgpProtoPrefix &proto_prefix,
47 : const BgpAttr *attr,
48 : const Address::Family family,
49 : Inet6VpnPrefix *prefix,
50 : BgpAttrPtr *new_attr, uint32_t *label,
51 : uint32_t *l3_label) {
52 49678 : return FromProtoPrefix(proto_prefix, prefix, label);
53 : }
54 :
55 55948 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
56 : BgpProtoPrefix *proto_prefix) const {
57 55948 : proto_prefix->prefix.clear();
58 55949 : size_t prefix_size = (prefixlen_ + 7) / 8;
59 55949 : size_t nlri_size =
60 55949 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
61 :
62 55949 : proto_prefix->prefix.resize(nlri_size, 0);
63 55944 : size_t label_offset = 0;
64 55944 : proto_prefix->WriteLabel(label_offset, label);
65 55944 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
66 55945 : copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
67 55944 : proto_prefix->prefix.begin() + rd_offset);
68 :
69 55945 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
70 55945 : proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
71 55945 : const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
72 55943 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
73 55944 : proto_prefix->prefix.begin() + prefix_offset);
74 55942 : }
75 :
76 : // RD:inet6-prefix
77 15210 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
78 : boost::system::error_code *errorp) {
79 15210 : Inet6VpnPrefix prefix;
80 :
81 15210 : size_t pos = str.find(':');
82 15210 : if (pos == string::npos) {
83 1 : if (errorp != NULL) {
84 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
85 : }
86 1 : return prefix;
87 : }
88 15209 : pos = str.find(':', (pos + 1));
89 15209 : if (pos == string::npos) {
90 1 : if (errorp != NULL) {
91 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
92 : }
93 1 : return prefix;
94 : }
95 15208 : string rdstr = str.substr(0, pos);
96 15208 : boost::system::error_code rderr;
97 15208 : prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
98 15208 : if (rderr.failed()) {
99 7 : if (errorp != NULL) {
100 5 : *errorp = rderr;
101 : }
102 7 : return prefix;
103 : }
104 :
105 15201 : string ip6pstr(str, pos + 1);
106 15201 : boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
107 : &prefix.prefixlen_);
108 15201 : if (errorp != NULL) {
109 1615 : *errorp = pfxerr;
110 : }
111 15201 : return prefix;
112 15208 : }
113 :
114 9 : string Inet6VpnPrefix::ToString() const {
115 9 : Inet6Prefix prefix(addr_, prefixlen_);
116 18 : return (rd_.ToString() + ":" + prefix.ToString());
117 : }
118 :
119 : // Check whether 'this' is more specific than rhs.
120 35 : bool Inet6VpnPrefix::IsMoreSpecific(const Inet6VpnPrefix &rhs) const {
121 35 : Inet6Prefix this_prefix(addr_, prefixlen_);
122 35 : Inet6Prefix match_prefix(rhs.addr(), rhs.prefixlen());
123 :
124 70 : return this_prefix.IsMoreSpecific(match_prefix);
125 : }
126 :
127 1490684 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
128 1490684 : int res = route_distinguisher().CompareTo(other.route_distinguisher());
129 1490850 : if (res != 0) {
130 882423 : return res;
131 : }
132 608427 : Ip6Address laddr = addr();
133 608394 : Ip6Address raddr = other.addr();
134 608340 : if (laddr < raddr) {
135 215215 : return -1;
136 : }
137 393572 : if (laddr > raddr) {
138 172306 : return 1;
139 : }
140 221232 : if (prefixlen() < other.prefixlen()) {
141 16 : return -1;
142 : }
143 221249 : if (prefixlen() > other.prefixlen()) {
144 8 : return 1;
145 : }
146 221233 : return 0;
147 : }
148 :
149 9 : bool Inet6VpnPrefix::operator==(const Inet6VpnPrefix &rhs) const {
150 18 : return (rd_ == rhs.rd_ && addr_ == rhs.addr_ &&
151 18 : prefixlen_ == rhs.prefixlen_);
152 : }
153 :
154 194862 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
155 194813 : }
156 :
157 1490763 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
158 1490763 : const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
159 1490763 : return prefix_.CompareTo(other.GetPrefix());
160 : }
161 :
162 431393 : string Inet6VpnRoute::ToString() const {
163 431393 : string repr = prefix_.route_distinguisher().ToString() + ":";
164 431414 : repr += prefix_.addr().to_string();
165 : char strplen[5];
166 431408 : snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
167 431406 : repr.append(strplen);
168 :
169 862826 : return repr;
170 0 : }
171 :
172 2 : void Inet6VpnRoute::SetKey(const DBRequestKey *reqkey) {
173 2 : const Inet6VpnTable::RequestKey *key =
174 : static_cast<const Inet6VpnTable::RequestKey *>(reqkey);
175 2 : prefix_ = key->prefix;
176 2 : }
177 :
178 55947 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
179 : const BgpAttr*,
180 : uint32_t label,
181 : uint32_t l3_label) const {
182 55947 : prefix_.BuildProtoPrefix(label, prefix);
183 55942 : }
184 :
185 : // XXX dest_nh should have been pointer. See if can change
186 30047 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
187 : IpAddress src_nh) const {
188 30047 : dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
189 30047 : 0);
190 30042 : Ip6Address source_addr;
191 30042 : if (src_nh.is_v4()) {
192 30041 : source_addr = Ip6Address::v4_mapped(src_nh.to_v4());
193 0 : } else if (src_nh.is_v6()) {
194 0 : source_addr = src_nh.to_v6();
195 : } else {
196 0 : assert(0);
197 : }
198 :
199 30050 : Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
200 30046 : copy(addr_bytes.begin(), addr_bytes.end(),
201 30045 : dest_nh.begin() + RouteDistinguisher::kSize);
202 30044 : }
203 :
204 58063 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
205 : Inet6VpnTable::RequestKey *key =
206 58063 : new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
207 58054 : return KeyPtr(key);
208 : }
209 :
210 : // Check whether 'this' is more specific than rhs.
211 22 : bool Inet6VpnRoute::IsMoreSpecific(const string &other) const {
212 22 : boost::system::error_code ec;
213 :
214 22 : Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
215 22 : if (!ec) {
216 22 : return GetPrefix().IsMoreSpecific(other_prefix);
217 : }
218 :
219 0 : return false;
220 : }
221 :
222 : // Check whether 'this' is less specific than rhs.
223 10 : bool Inet6VpnRoute::IsLessSpecific(const string &other) const {
224 10 : boost::system::error_code ec;
225 :
226 10 : Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
227 10 : if (!ec) {
228 10 : return other_prefix.IsMoreSpecific(GetPrefix());
229 : }
230 :
231 0 : return false;
232 : }
|