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 1027612 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute() {
22 1027612 : value1 = 0; // reset all fields
23 1027612 : value2 = 0; // reset all fields
24 1027612 : type = BgpExtendedCommunityType::Opaque;
25 1027612 : sub_type = BgpExtendedCommunityOpaqueSubType::LoadBalance;
26 :
27 1027612 : l3_source_address = true;
28 1027612 : l3_destination_address = true;
29 1027612 : l4_protocol = true;
30 1027612 : l4_source_port = true;
31 1027612 : l4_destination_port = true;
32 1027612 : reserved1 = false;
33 :
34 1027612 : reserved2 = 0;
35 :
36 1027612 : source_bias = false;
37 :
38 1027612 : reserved3 = 0;
39 1027612 : reserved4 = 0;
40 1027612 : reserved5 = 0;
41 1027612 : }
42 :
43 130078 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute(
44 130078 : uint32_t value1, uint32_t value2) : value1(value1), value2(value2) {
45 130078 : }
46 :
47 22005 : void LoadBalance::LoadBalanceAttribute::Encode(
48 : autogen::LoadBalanceType *lb_type) const {
49 22005 : lb_type->load_balance_fields.load_balance_field_list.clear();
50 22005 : if (l3_source_address)
51 22002 : lb_type->load_balance_fields.load_balance_field_list.push_back(
52 44004 : string("l3-source-address"));
53 22005 : if (l3_destination_address)
54 21999 : lb_type->load_balance_fields.load_balance_field_list.push_back(
55 43998 : string("l3-destination-address"));
56 22005 : if (l4_protocol)
57 22002 : lb_type->load_balance_fields.load_balance_field_list.push_back(
58 44004 : string("l4-protocol"));
59 22005 : if (l4_source_port)
60 21999 : lb_type->load_balance_fields.load_balance_field_list.push_back(
61 43998 : string("l4-source-port"));
62 22005 : if (l4_destination_port)
63 22002 : lb_type->load_balance_fields.load_balance_field_list.push_back(
64 44004 : string("l4-destination-port"));
65 22005 : lb_type->load_balance_decision = source_bias ? "source-bias" : "field-hash";
66 22005 : }
67 :
68 573859 : bool LoadBalance::LoadBalanceAttribute::operator==(
69 : const LoadBalance::LoadBalanceAttribute &other) const {
70 573859 : return value1 == other.value1 && value2 == other.value2;
71 : }
72 :
73 42192 : bool LoadBalance::LoadBalanceAttribute::operator!=(
74 : const LoadBalance::LoadBalanceAttribute &other) const {
75 42192 : return value1 != other.value1 || value2 != other.value2;
76 : }
77 :
78 528586 : const bool LoadBalance::LoadBalanceAttribute::IsDefault() const {
79 528586 : return *this == kDefaultLoadBalanceAttribute;
80 : }
81 :
82 86291 : LoadBalance::LoadBalance() {
83 86291 : LoadBalanceAttribute attr;
84 86291 : put_value(&data_[0], 4, attr.value1);
85 86291 : put_value(&data_[4], 4, attr.value2);
86 86291 : }
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 64152 : LoadBalance::LoadBalance(const autogen::LoadBalanceType &lb_type) {
116 64152 : LoadBalanceAttribute attr;
117 :
118 64152 : 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 128293 : !attr.source_bias && (lb_type.load_balance_fields.begin() ==
125 64143 : lb_type.load_balance_fields.end());
126 64152 : attr.l3_source_address = load_balance_default || false;
127 64152 : attr.l3_destination_address = load_balance_default || false;
128 64152 : attr.l4_protocol = load_balance_default || false;
129 64152 : attr.l4_source_port = load_balance_default || false;
130 64152 : attr.l4_destination_port = load_balance_default || false;
131 :
132 64150 : for (autogen::LoadBalanceFieldListType::const_iterator it =
133 64152 : lb_type.load_balance_fields.begin();
134 174049 : it != lb_type.load_balance_fields.end(); ++it) {
135 109894 : const string s = *it;
136 109894 : if (s == "l3-source-address") {
137 21981 : attr.l3_source_address = true;
138 21981 : continue;
139 : }
140 87918 : if (s == "l3-destination-address") {
141 21978 : attr.l3_destination_address = true;
142 21978 : continue;
143 : }
144 65940 : if (s == "l4-protocol") {
145 21981 : attr.l4_protocol = true;
146 21981 : continue;
147 : }
148 43959 : if (s == "l4-source-port") {
149 21978 : attr.l4_source_port = true;
150 21978 : continue;
151 : }
152 21981 : if (s == "l4-destination-port") {
153 21981 : attr.l4_destination_port = true;
154 21981 : continue;
155 : }
156 109899 : }
157 :
158 64153 : put_value(&data_[0], 4, attr.value1);
159 64153 : put_value(&data_[4], 4, attr.value2);
160 64153 : }
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 130078 : const LoadBalance::LoadBalanceAttribute LoadBalance::ToAttribute() const {
168 130078 : return LoadBalanceAttribute(
169 130078 : get_value_unaligned(&data_[0], 4),
170 260156 : 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 18740 : bool LoadBalance::IsPresent(const BgpPath *path) {
222 18740 : if (!path)
223 0 : return false;
224 18740 : const BgpAttr *attr = path->GetAttr();
225 18740 : if (!attr)
226 0 : return false;
227 18740 : const ExtCommunity *ext_community = attr->ext_community();
228 18740 : if (!ext_community)
229 32 : return false;
230 83486 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
231 : ext_community->communities()) {
232 32581 : if (ExtCommunity::is_load_balance(comm)) {
233 192 : return true;
234 : }
235 : }
236 18516 : return false;
237 : }
238 :
239 44955 : const bool LoadBalance::IsDefault() const {
240 44955 : return ToAttribute() == LoadBalanceAttribute::kDefaultLoadBalanceAttribute;
241 : }
242 :
243 320 : bool LoadBalance::operator==(const LoadBalance &other) const {
244 320 : return ToAttribute() == other.ToAttribute();
245 : }
246 :
247 42188 : bool LoadBalance::operator!=(const LoadBalance &other) const {
248 42188 : 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 : }
|