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 1026147 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute() {
22 1026147 : value1 = 0; // reset all fields
23 1026147 : value2 = 0; // reset all fields
24 1026147 : type = BgpExtendedCommunityType::Opaque;
25 1026147 : sub_type = BgpExtendedCommunityOpaqueSubType::LoadBalance;
26 :
27 1026147 : l3_source_address = true;
28 1026147 : l3_destination_address = true;
29 1026147 : l4_protocol = true;
30 1026147 : l4_source_port = true;
31 1026147 : l4_destination_port = true;
32 1026147 : reserved1 = false;
33 :
34 1026147 : reserved2 = 0;
35 :
36 1026147 : source_bias = false;
37 :
38 1026147 : reserved3 = 0;
39 1026147 : reserved4 = 0;
40 1026147 : reserved5 = 0;
41 1026147 : }
42 :
43 130071 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute(
44 130071 : uint32_t value1, uint32_t value2) : value1(value1), value2(value2) {
45 130071 : }
46 :
47 22004 : void LoadBalance::LoadBalanceAttribute::Encode(
48 : autogen::LoadBalanceType *lb_type) const {
49 22004 : lb_type->load_balance_fields.load_balance_field_list.clear();
50 22004 : if (l3_source_address)
51 22001 : lb_type->load_balance_fields.load_balance_field_list.push_back(
52 44002 : string("l3-source-address"));
53 22004 : if (l3_destination_address)
54 21998 : lb_type->load_balance_fields.load_balance_field_list.push_back(
55 43996 : string("l3-destination-address"));
56 22004 : if (l4_protocol)
57 22001 : lb_type->load_balance_fields.load_balance_field_list.push_back(
58 44002 : string("l4-protocol"));
59 22004 : if (l4_source_port)
60 21998 : lb_type->load_balance_fields.load_balance_field_list.push_back(
61 43996 : string("l4-source-port"));
62 22004 : if (l4_destination_port)
63 22001 : lb_type->load_balance_fields.load_balance_field_list.push_back(
64 44002 : string("l4-destination-port"));
65 22004 : lb_type->load_balance_decision = source_bias ? "source-bias" : "field-hash";
66 22004 : }
67 :
68 572461 : bool LoadBalance::LoadBalanceAttribute::operator==(
69 : const LoadBalance::LoadBalanceAttribute &other) const {
70 572461 : return value1 == other.value1 && value2 == other.value2;
71 : }
72 :
73 42191 : bool LoadBalance::LoadBalanceAttribute::operator!=(
74 : const LoadBalance::LoadBalanceAttribute &other) const {
75 42191 : return value1 != other.value1 || value2 != other.value2;
76 : }
77 :
78 527211 : const bool LoadBalance::LoadBalanceAttribute::IsDefault() const {
79 527211 : return *this == kDefaultLoadBalanceAttribute;
80 : }
81 :
82 86402 : LoadBalance::LoadBalance() {
83 86402 : LoadBalanceAttribute attr;
84 86402 : put_value(&data_[0], 4, attr.value1);
85 86402 : put_value(&data_[4], 4, attr.value2);
86 86402 : }
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 64147 : LoadBalance::LoadBalance(const autogen::LoadBalanceType &lb_type) {
116 64147 : LoadBalanceAttribute attr;
117 :
118 64147 : 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 128285 : !attr.source_bias && (lb_type.load_balance_fields.begin() ==
125 64138 : lb_type.load_balance_fields.end());
126 64147 : attr.l3_source_address = load_balance_default || false;
127 64147 : attr.l3_destination_address = load_balance_default || false;
128 64147 : attr.l4_protocol = load_balance_default || false;
129 64147 : attr.l4_source_port = load_balance_default || false;
130 64147 : attr.l4_destination_port = load_balance_default || false;
131 :
132 64147 : for (autogen::LoadBalanceFieldListType::const_iterator it =
133 64147 : lb_type.load_balance_fields.begin();
134 174024 : it != lb_type.load_balance_fields.end(); ++it) {
135 109875 : const string s = *it;
136 109874 : if (s == "l3-source-address") {
137 21976 : attr.l3_source_address = true;
138 21976 : continue;
139 : }
140 87901 : if (s == "l3-destination-address") {
141 21974 : attr.l3_destination_address = true;
142 21974 : continue;
143 : }
144 65927 : if (s == "l4-protocol") {
145 21977 : attr.l4_protocol = true;
146 21977 : continue;
147 : }
148 43950 : if (s == "l4-source-port") {
149 21974 : attr.l4_source_port = true;
150 21974 : continue;
151 : }
152 21976 : if (s == "l4-destination-port") {
153 21976 : attr.l4_destination_port = true;
154 21976 : continue;
155 : }
156 109877 : }
157 :
158 64147 : put_value(&data_[0], 4, attr.value1);
159 64147 : put_value(&data_[4], 4, attr.value2);
160 64147 : }
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 130071 : const LoadBalance::LoadBalanceAttribute LoadBalance::ToAttribute() const {
168 130071 : return LoadBalanceAttribute(
169 130071 : get_value_unaligned(&data_[0], 4),
170 260143 : 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 18862 : bool LoadBalance::IsPresent(const BgpPath *path) {
222 18862 : if (!path)
223 0 : return false;
224 18862 : const BgpAttr *attr = path->GetAttr();
225 18862 : if (!attr)
226 0 : return false;
227 18862 : const ExtCommunity *ext_community = attr->ext_community();
228 18862 : if (!ext_community)
229 32 : return false;
230 84390 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
231 : ext_community->communities()) {
232 32972 : if (ExtCommunity::is_load_balance(comm)) {
233 192 : return true;
234 : }
235 : }
236 18638 : return false;
237 : }
238 :
239 44950 : const bool LoadBalance::IsDefault() const {
240 44950 : return ToAttribute() == LoadBalanceAttribute::kDefaultLoadBalanceAttribute;
241 : }
242 :
243 320 : bool LoadBalance::operator==(const LoadBalance &other) const {
244 320 : return ToAttribute() == other.ToAttribute();
245 : }
246 :
247 42187 : bool LoadBalance::operator!=(const LoadBalance &other) const {
248 42187 : 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 : }
|