Line data Source code
1 : /*
2 : * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/extended-community/load_balance.h"
6 :
7 : #include <boost/foreach.hpp>
8 :
9 : #include <algorithm>
10 : #include <string>
11 : #include <vector>
12 :
13 : using std::copy;
14 : using std::string;
15 :
16 : // Initialize default attribute statically.
17 : const LoadBalance::LoadBalanceAttribute
18 : LoadBalance::LoadBalanceAttribute::kDefaultLoadBalanceAttribute =
19 : LoadBalance::LoadBalanceAttribute();
20 :
21 1027261 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute() {
22 1027261 : value1 = 0; // reset all fields
23 1027261 : value2 = 0; // reset all fields
24 1027261 : type = BgpExtendedCommunityType::Opaque;
25 1027261 : sub_type = BgpExtendedCommunityOpaqueSubType::LoadBalance;
26 :
27 1027261 : l3_source_address = true;
28 1027261 : l3_destination_address = true;
29 1027261 : l4_protocol = true;
30 1027261 : l4_source_port = true;
31 1027261 : l4_destination_port = true;
32 1027261 : reserved1 = false;
33 :
34 1027261 : reserved2 = 0;
35 :
36 1027261 : source_bias = false;
37 :
38 1027261 : reserved3 = 0;
39 1027261 : reserved4 = 0;
40 1027261 : reserved5 = 0;
41 1027261 : }
42 :
43 130081 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute(
44 130081 : uint32_t value1, uint32_t value2) : value1(value1), value2(value2) {
45 130081 : }
46 :
47 22003 : void LoadBalance::LoadBalanceAttribute::Encode(
48 : autogen::LoadBalanceType *lb_type) const {
49 22003 : lb_type->load_balance_fields.load_balance_field_list.clear();
50 22003 : if (l3_source_address)
51 22000 : lb_type->load_balance_fields.load_balance_field_list.push_back(
52 44000 : string("l3-source-address"));
53 22003 : if (l3_destination_address)
54 21997 : lb_type->load_balance_fields.load_balance_field_list.push_back(
55 43994 : string("l3-destination-address"));
56 22003 : if (l4_protocol)
57 22000 : lb_type->load_balance_fields.load_balance_field_list.push_back(
58 44000 : string("l4-protocol"));
59 22003 : if (l4_source_port)
60 21997 : lb_type->load_balance_fields.load_balance_field_list.push_back(
61 43994 : string("l4-source-port"));
62 22003 : if (l4_destination_port)
63 22000 : lb_type->load_balance_fields.load_balance_field_list.push_back(
64 44000 : string("l4-destination-port"));
65 22003 : lb_type->load_balance_decision = source_bias ? "source-bias" : "field-hash";
66 22003 : }
67 :
68 573476 : bool LoadBalance::LoadBalanceAttribute::operator==(
69 : const LoadBalance::LoadBalanceAttribute &other) const {
70 573476 : return value1 == other.value1 && value2 == other.value2;
71 : }
72 :
73 42194 : bool LoadBalance::LoadBalanceAttribute::operator!=(
74 : const LoadBalance::LoadBalanceAttribute &other) const {
75 42194 : return value1 != other.value1 || value2 != other.value2;
76 : }
77 :
78 528173 : const bool LoadBalance::LoadBalanceAttribute::IsDefault() const {
79 528173 : return *this == kDefaultLoadBalanceAttribute;
80 : }
81 :
82 86395 : LoadBalance::LoadBalance() {
83 86395 : LoadBalanceAttribute attr;
84 86395 : put_value(&data_[0], 4, attr.value1);
85 86395 : put_value(&data_[4], 4, attr.value2);
86 86395 : }
87 :
88 476 : LoadBalance::LoadBalance(const bytes_type &data) {
89 476 : copy(data.begin(), data.end(), data_.begin());
90 476 : }
91 :
92 8 : LoadBalance::LoadBalance(const BgpPath *path) {
93 8 : LoadBalance();
94 8 : if (!path)
95 0 : return;
96 8 : const BgpAttr *attr = path->GetAttr();
97 8 : if (!attr)
98 0 : return;
99 8 : const ExtCommunity *ext_community = attr->ext_community();
100 8 : if (!ext_community)
101 0 : return;
102 32 : for (const auto &comm : ext_community->communities()) {
103 32 : if (ExtCommunity::is_load_balance(comm)) {
104 8 : copy(comm.begin(), comm.end(), data_.begin());
105 8 : break;
106 : }
107 : }
108 : }
109 :
110 5 : LoadBalance::LoadBalance(const LoadBalanceAttribute &attr) {
111 5 : put_value(&data_[0], 4, attr.value1);
112 5 : put_value(&data_[4], 4, attr.value2);
113 5 : }
114 :
115 64154 : LoadBalance::LoadBalance(const autogen::LoadBalanceType &lb_type) {
116 64154 : LoadBalanceAttribute attr;
117 :
118 64154 : attr.source_bias = lb_type.load_balance_decision == "source-bias";
119 :
120 : // autogen::LoadBalanceType fields list empty should imply as standard
121 : // 5-tuple fields set. xml schema does not let one specifify default values
122 : // for a complex type such as a list in this case.
123 : bool load_balance_default =
124 128299 : !attr.source_bias && (lb_type.load_balance_fields.begin() ==
125 64145 : lb_type.load_balance_fields.end());
126 64154 : attr.l3_source_address = load_balance_default || false;
127 64154 : attr.l3_destination_address = load_balance_default || false;
128 64154 : attr.l4_protocol = load_balance_default || false;
129 64154 : attr.l4_source_port = load_balance_default || false;
130 64154 : attr.l4_destination_port = load_balance_default || false;
131 :
132 64154 : for (autogen::LoadBalanceFieldListType::const_iterator it =
133 64154 : lb_type.load_balance_fields.begin();
134 174048 : it != lb_type.load_balance_fields.end(); ++it) {
135 109894 : const string s = *it;
136 109894 : if (s == "l3-source-address") {
137 21980 : attr.l3_source_address = true;
138 21980 : continue;
139 : }
140 87914 : if (s == "l3-destination-address") {
141 21977 : attr.l3_destination_address = true;
142 21977 : continue;
143 : }
144 65937 : if (s == "l4-protocol") {
145 21980 : attr.l4_protocol = true;
146 21980 : continue;
147 : }
148 43957 : if (s == "l4-source-port") {
149 21977 : attr.l4_source_port = true;
150 21977 : continue;
151 : }
152 21980 : if (s == "l4-destination-port") {
153 21980 : attr.l4_destination_port = true;
154 21980 : continue;
155 : }
156 109894 : }
157 :
158 64153 : put_value(&data_[0], 4, attr.value1);
159 64153 : put_value(&data_[4], 4, attr.value2);
160 64154 : }
161 :
162 4 : void LoadBalance::FillAttribute(LoadBalanceAttribute *attr) {
163 4 : attr->value1 = get_value(&data_[0], 4);
164 4 : attr->value2 = get_value(&data_[4], 4);
165 4 : }
166 :
167 130081 : const LoadBalance::LoadBalanceAttribute LoadBalance::ToAttribute() const {
168 130081 : return LoadBalanceAttribute(
169 130081 : get_value_unaligned(&data_[0], 4),
170 260162 : get_value_unaligned(&data_[4], 4));
171 : }
172 :
173 35 : void LoadBalance::SetL3SourceAddress(bool flag) {
174 35 : LoadBalanceAttribute attr = ToAttribute();
175 35 : attr.l3_source_address = flag;
176 :
177 35 : put_value(&data_[0], 4, attr.value1);
178 35 : put_value(&data_[4], 4, attr.value2);
179 35 : }
180 :
181 35 : void LoadBalance::SetL3DestinationAddress(bool flag) {
182 35 : LoadBalanceAttribute attr = ToAttribute();
183 35 : attr.l3_destination_address = flag;
184 :
185 35 : put_value(&data_[0], 4, attr.value1);
186 35 : put_value(&data_[4], 4, attr.value2);
187 35 : }
188 :
189 1 : void LoadBalance::SetL4Protocol(bool flag) {
190 1 : LoadBalanceAttribute attr = ToAttribute();
191 1 : attr.l4_protocol = flag;
192 :
193 1 : put_value(&data_[0], 4, attr.value1);
194 1 : put_value(&data_[4], 4, attr.value2);
195 1 : }
196 :
197 1 : void LoadBalance::SetL4SourcePort(bool flag) {
198 1 : LoadBalanceAttribute attr = ToAttribute();
199 1 : attr.l4_source_port = flag;
200 :
201 1 : put_value(&data_[0], 4, attr.value1);
202 1 : put_value(&data_[4], 4, attr.value2);
203 1 : }
204 :
205 1 : void LoadBalance::SetL4DestinationPort(bool flag) {
206 1 : LoadBalanceAttribute attr = ToAttribute();
207 1 : attr.l4_destination_port = flag;
208 :
209 1 : put_value(&data_[0], 4, attr.value1);
210 1 : put_value(&data_[4], 4, attr.value2);
211 1 : }
212 :
213 1 : void LoadBalance::SetSourceBias(bool flag) {
214 1 : LoadBalanceAttribute attr = ToAttribute();
215 1 : attr.source_bias = flag;
216 :
217 1 : put_value(&data_[0], 4, attr.value1);
218 1 : put_value(&data_[4], 4, attr.value2);
219 1 : }
220 :
221 18868 : bool LoadBalance::IsPresent(const BgpPath *path) {
222 18868 : if (!path)
223 0 : return false;
224 18868 : const BgpAttr *attr = path->GetAttr();
225 18868 : if (!attr)
226 0 : return false;
227 18868 : const ExtCommunity *ext_community = attr->ext_community();
228 18868 : if (!ext_community)
229 32 : return false;
230 84384 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
231 : ext_community->communities()) {
232 32966 : if (ExtCommunity::is_load_balance(comm)) {
233 192 : return true;
234 : }
235 : }
236 18644 : return false;
237 : }
238 :
239 44954 : const bool LoadBalance::IsDefault() const {
240 44954 : return ToAttribute() == LoadBalanceAttribute::kDefaultLoadBalanceAttribute;
241 : }
242 :
243 320 : bool LoadBalance::operator==(const LoadBalance &other) const {
244 320 : return ToAttribute() == other.ToAttribute();
245 : }
246 :
247 42190 : bool LoadBalance::operator!=(const LoadBalance &other) const {
248 42190 : return ToAttribute() != other.ToAttribute();
249 : }
250 :
251 6 : void LoadBalance::ShowAttribute(ShowLoadBalance *show_load_balance) const {
252 6 : const LoadBalanceAttribute attr = ToAttribute();
253 6 : vector<string> fields = vector<string>();
254 6 : if (attr.source_bias) {
255 3 : show_load_balance->set_decision_type("source-bias");
256 3 : show_load_balance->set_fields(fields);
257 3 : return;
258 : }
259 :
260 3 : show_load_balance->set_decision_type("field-hash");
261 3 : if (attr.l3_source_address)
262 2 : fields.push_back("l3-source-address");
263 3 : if (attr.l3_destination_address)
264 3 : fields.push_back("l3-destination-address");
265 3 : if (attr.l4_protocol)
266 2 : fields.push_back("l4-protocol");
267 3 : if (attr.l4_source_port)
268 3 : fields.push_back("l4-source-port");
269 3 : if (attr.l4_destination_port)
270 2 : fields.push_back("l4-destination-port");
271 3 : show_load_balance->set_fields(fields);
272 6 : }
273 :
274 6 : string LoadBalance::ToString() const {
275 6 : const LoadBalanceAttribute attr = ToAttribute();
276 6 : string str("load-balance:");
277 6 : str += attr.source_bias ? "source-bias" : "field-hash";
278 12 : return str;
279 0 : }
|