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 64833 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
17 64833 : }
18 :
19 49626 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
20 : Inet6VpnPrefix *prefix, uint32_t *label) {
21 49626 : size_t nlri_size = proto_prefix.prefix.size();
22 49626 : size_t expected_min_nlri_size =
23 49626 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
24 :
25 49626 : if (nlri_size < expected_min_nlri_size)
26 1 : return -1;
27 49625 : if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
28 1 : return -1;
29 :
30 49624 : size_t label_offset = 0;
31 49624 : *label = proto_prefix.ReadLabel(label_offset);
32 49624 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
33 49624 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
34 :
35 49624 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
36 49624 : prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
37 49624 : Ip6Address::bytes_type bt = { { 0 } };
38 49624 : copy(proto_prefix.prefix.begin() + prefix_offset,
39 : proto_prefix.prefix.end(), bt.begin());
40 49624 : prefix->addr_ = Ip6Address(bt);
41 :
42 49624 : return 0;
43 : }
44 :
45 49621 : 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 49621 : return FromProtoPrefix(proto_prefix, prefix, label);
53 : }
54 :
55 56436 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
56 : BgpProtoPrefix *proto_prefix) const {
57 56436 : proto_prefix->prefix.clear();
58 56435 : size_t prefix_size = (prefixlen_ + 7) / 8;
59 56435 : size_t nlri_size =
60 56435 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
61 :
62 56435 : proto_prefix->prefix.resize(nlri_size, 0);
63 56429 : size_t label_offset = 0;
64 56429 : proto_prefix->WriteLabel(label_offset, label);
65 56428 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
66 56428 : copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
67 56428 : proto_prefix->prefix.begin() + rd_offset);
68 :
69 56419 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
70 56419 : proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
71 56419 : const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
72 56418 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
73 56419 : proto_prefix->prefix.begin() + prefix_offset);
74 56417 : }
75 :
76 : // RD:inet6-prefix
77 15205 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
78 : boost::system::error_code *errorp) {
79 15205 : Inet6VpnPrefix prefix;
80 :
81 15205 : size_t pos = str.find(':');
82 15205 : 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 15204 : pos = str.find(':', (pos + 1));
89 15204 : 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 15203 : string rdstr = str.substr(0, pos);
96 15203 : boost::system::error_code rderr;
97 15203 : prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
98 15203 : if (rderr.failed()) {
99 7 : if (errorp != NULL) {
100 5 : *errorp = rderr;
101 : }
102 7 : return prefix;
103 : }
104 :
105 15196 : string ip6pstr(str, pos + 1);
106 15196 : boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
107 : &prefix.prefixlen_);
108 15196 : if (errorp != NULL) {
109 1610 : *errorp = pfxerr;
110 : }
111 15196 : return prefix;
112 15203 : }
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 1494097 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
128 1494097 : int res = route_distinguisher().CompareTo(other.route_distinguisher());
129 1494285 : if (res != 0) {
130 885594 : return res;
131 : }
132 608691 : Ip6Address laddr = addr();
133 608640 : Ip6Address raddr = other.addr();
134 608594 : if (laddr < raddr) {
135 215004 : return -1;
136 : }
137 394043 : if (laddr > raddr) {
138 172360 : return 1;
139 : }
140 221652 : if (prefixlen() < other.prefixlen()) {
141 16 : return -1;
142 : }
143 221670 : if (prefixlen() > other.prefixlen()) {
144 8 : return 1;
145 : }
146 221657 : 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 195407 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
155 195363 : }
156 :
157 1494199 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
158 1494199 : const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
159 1494199 : return prefix_.CompareTo(other.GetPrefix());
160 : }
161 :
162 446534 : string Inet6VpnRoute::ToString() const {
163 446534 : string repr = prefix_.route_distinguisher().ToString() + ":";
164 446544 : repr += prefix_.addr().to_string();
165 : char strplen[5];
166 446527 : snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
167 446467 : repr.append(strplen);
168 :
169 893082 : 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 56434 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
179 : const BgpAttr*,
180 : uint32_t label,
181 : uint32_t l3_label) const {
182 56434 : prefix_.BuildProtoPrefix(label, prefix);
183 56417 : }
184 :
185 : // XXX dest_nh should have been pointer. See if can change
186 30209 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
187 : IpAddress src_nh) const {
188 30209 : dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
189 30209 : 0);
190 30205 : Ip6Address source_addr;
191 30205 : if (src_nh.is_v4()) {
192 30205 : 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 30213 : Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
200 30212 : copy(addr_bytes.begin(), addr_bytes.end(),
201 30212 : dest_nh.begin() + RouteDistinguisher::kSize);
202 30211 : }
203 :
204 58686 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
205 : Inet6VpnTable::RequestKey *key =
206 58686 : new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
207 58674 : 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 : }
|