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 64978 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
17 64978 : }
18 :
19 49798 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
20 : Inet6VpnPrefix *prefix, uint32_t *label) {
21 49798 : size_t nlri_size = proto_prefix.prefix.size();
22 49798 : size_t expected_min_nlri_size =
23 49798 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
24 :
25 49798 : if (nlri_size < expected_min_nlri_size)
26 1 : return -1;
27 49797 : if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
28 1 : return -1;
29 :
30 49796 : size_t label_offset = 0;
31 49796 : *label = proto_prefix.ReadLabel(label_offset);
32 49796 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
33 49796 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
34 :
35 49796 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
36 49796 : prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
37 49796 : Ip6Address::bytes_type bt = { { 0 } };
38 49796 : copy(proto_prefix.prefix.begin() + prefix_offset,
39 : proto_prefix.prefix.end(), bt.begin());
40 49796 : prefix->addr_ = Ip6Address(bt);
41 :
42 49796 : return 0;
43 : }
44 :
45 49793 : 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 49793 : return FromProtoPrefix(proto_prefix, prefix, label);
53 : }
54 :
55 56487 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
56 : BgpProtoPrefix *proto_prefix) const {
57 56487 : proto_prefix->prefix.clear();
58 56488 : size_t prefix_size = (prefixlen_ + 7) / 8;
59 56488 : size_t nlri_size =
60 56488 : BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
61 :
62 56488 : proto_prefix->prefix.resize(nlri_size, 0);
63 56486 : size_t label_offset = 0;
64 56486 : proto_prefix->WriteLabel(label_offset, label);
65 56483 : size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
66 56483 : copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
67 56483 : proto_prefix->prefix.begin() + rd_offset);
68 :
69 56480 : size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
70 56480 : proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
71 56480 : const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
72 56479 : copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
73 56480 : proto_prefix->prefix.begin() + prefix_offset);
74 56480 : }
75 :
76 : // RD:inet6-prefix
77 15178 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
78 : boost::system::error_code *errorp) {
79 15178 : Inet6VpnPrefix prefix;
80 :
81 15178 : size_t pos = str.find(':');
82 15178 : 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 15177 : pos = str.find(':', (pos + 1));
89 15177 : 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 15176 : string rdstr = str.substr(0, pos);
96 15176 : boost::system::error_code rderr;
97 15176 : prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
98 15176 : if (rderr.failed()) {
99 7 : if (errorp != NULL) {
100 5 : *errorp = rderr;
101 : }
102 7 : return prefix;
103 : }
104 :
105 15169 : string ip6pstr(str, pos + 1);
106 15169 : boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
107 : &prefix.prefixlen_);
108 15169 : if (errorp != NULL) {
109 1589 : *errorp = pfxerr;
110 : }
111 15169 : return prefix;
112 15176 : }
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 1496701 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
128 1496701 : int res = route_distinguisher().CompareTo(other.route_distinguisher());
129 1496798 : if (res != 0) {
130 886124 : return res;
131 : }
132 610674 : Ip6Address laddr = addr();
133 610645 : Ip6Address raddr = other.addr();
134 610612 : if (laddr < raddr) {
135 215788 : return -1;
136 : }
137 395160 : if (laddr > raddr) {
138 173037 : return 1;
139 : }
140 222103 : if (prefixlen() < other.prefixlen()) {
141 16 : return -1;
142 : }
143 222089 : if (prefixlen() > other.prefixlen()) {
144 8 : return 1;
145 : }
146 222070 : 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 195728 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
155 195699 : }
156 :
157 1496738 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
158 1496738 : const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
159 1496738 : return prefix_.CompareTo(other.GetPrefix());
160 : }
161 :
162 433349 : string Inet6VpnRoute::ToString() const {
163 433349 : string repr = prefix_.route_distinguisher().ToString() + ":";
164 433351 : repr += prefix_.addr().to_string();
165 : char strplen[5];
166 433347 : snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
167 433343 : repr.append(strplen);
168 :
169 866696 : 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 56486 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
179 : const BgpAttr*,
180 : uint32_t label,
181 : uint32_t l3_label) const {
182 56486 : prefix_.BuildProtoPrefix(label, prefix);
183 56480 : }
184 :
185 : // XXX dest_nh should have been pointer. See if can change
186 30156 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
187 : IpAddress src_nh) const {
188 30156 : dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
189 30156 : 0);
190 30153 : Ip6Address source_addr;
191 30153 : if (src_nh.is_v4()) {
192 30153 : 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 30158 : Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
200 30156 : copy(addr_bytes.begin(), addr_bytes.end(),
201 30157 : dest_nh.begin() + RouteDistinguisher::kSize);
202 30155 : }
203 :
204 58761 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
205 : Inet6VpnTable::RequestKey *key =
206 58761 : new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
207 58761 : 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 : }
|