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 1027644 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute() {
22 1027644 : value1 = 0; // reset all fields
23 1027644 : value2 = 0; // reset all fields
24 1027644 : type = BgpExtendedCommunityType::Opaque;
25 1027644 : sub_type = BgpExtendedCommunityOpaqueSubType::LoadBalance;
26 :
27 1027644 : l3_source_address = true;
28 1027644 : l3_destination_address = true;
29 1027644 : l4_protocol = true;
30 1027644 : l4_source_port = true;
31 1027644 : l4_destination_port = true;
32 1027644 : reserved1 = false;
33 :
34 1027644 : reserved2 = 0;
35 :
36 1027644 : source_bias = false;
37 :
38 1027644 : reserved3 = 0;
39 1027644 : reserved4 = 0;
40 1027644 : reserved5 = 0;
41 1027644 : }
42 :
43 130081 : LoadBalance::LoadBalanceAttribute::LoadBalanceAttribute(
44 130081 : uint32_t value1, uint32_t value2) : value1(value1), value2(value2) {
45 130081 : }
46 :
47 22006 : void LoadBalance::LoadBalanceAttribute::Encode(
48 : autogen::LoadBalanceType *lb_type) const {
49 22006 : lb_type->load_balance_fields.load_balance_field_list.clear();
50 22006 : if (l3_source_address)
51 22003 : lb_type->load_balance_fields.load_balance_field_list.push_back(
52 44006 : string("l3-source-address"));
53 22006 : if (l3_destination_address)
54 22000 : lb_type->load_balance_fields.load_balance_field_list.push_back(
55 44000 : string("l3-destination-address"));
56 22006 : if (l4_protocol)
57 22003 : lb_type->load_balance_fields.load_balance_field_list.push_back(
58 44006 : string("l4-protocol"));
59 22006 : if (l4_source_port)
60 22000 : lb_type->load_balance_fields.load_balance_field_list.push_back(
61 44000 : string("l4-source-port"));
62 22006 : if (l4_destination_port)
63 22003 : lb_type->load_balance_fields.load_balance_field_list.push_back(
64 44006 : string("l4-destination-port"));
65 22006 : lb_type->load_balance_decision = source_bias ? "source-bias" : "field-hash";
66 22006 : }
67 :
68 573914 : bool LoadBalance::LoadBalanceAttribute::operator==(
69 : const LoadBalance::LoadBalanceAttribute &other) const {
70 573914 : 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 528629 : const bool LoadBalance::LoadBalanceAttribute::IsDefault() const {
79 528629 : return *this == kDefaultLoadBalanceAttribute;
80 : }
81 :
82 86452 : LoadBalance::LoadBalance() {
83 86452 : LoadBalanceAttribute attr;
84 86452 : put_value(&data_[0], 4, attr.value1);
85 86452 : put_value(&data_[4], 4, attr.value2);
86 86452 : }
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 64156 : LoadBalance::LoadBalance(const autogen::LoadBalanceType &lb_type) {
116 64156 : LoadBalanceAttribute attr;
117 :
118 64156 : 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 128303 : !attr.source_bias && (lb_type.load_balance_fields.begin() ==
125 64147 : lb_type.load_balance_fields.end());
126 64156 : attr.l3_source_address = load_balance_default || false;
127 64156 : attr.l3_destination_address = load_balance_default || false;
128 64156 : attr.l4_protocol = load_balance_default || false;
129 64156 : attr.l4_source_port = load_balance_default || false;
130 64156 : attr.l4_destination_port = load_balance_default || false;
131 :
132 64156 : for (autogen::LoadBalanceFieldListType::const_iterator it =
133 64156 : lb_type.load_balance_fields.begin();
134 174069 : it != lb_type.load_balance_fields.end(); ++it) {
135 109913 : const string s = *it;
136 109913 : if (s == "l3-source-address") {
137 21984 : attr.l3_source_address = true;
138 21984 : continue;
139 : }
140 87930 : if (s == "l3-destination-address") {
141 21981 : attr.l3_destination_address = true;
142 21981 : continue;
143 : }
144 65949 : if (s == "l4-protocol") {
145 21984 : attr.l4_protocol = true;
146 21984 : continue;
147 : }
148 43965 : if (s == "l4-source-port") {
149 21981 : attr.l4_source_port = true;
150 21981 : continue;
151 : }
152 21984 : if (s == "l4-destination-port") {
153 21984 : attr.l4_destination_port = true;
154 21984 : continue;
155 : }
156 109914 : }
157 :
158 64156 : put_value(&data_[0], 4, attr.value1);
159 64156 : put_value(&data_[4], 4, attr.value2);
160 64156 : }
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 18940 : bool LoadBalance::IsPresent(const BgpPath *path) {
222 18940 : if (!path)
223 0 : return false;
224 18940 : const BgpAttr *attr = path->GetAttr();
225 18940 : if (!attr)
226 0 : return false;
227 18940 : const ExtCommunity *ext_community = attr->ext_community();
228 18940 : if (!ext_community)
229 32 : return false;
230 85098 : BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
231 : ext_community->communities()) {
232 33287 : if (ExtCommunity::is_load_balance(comm)) {
233 192 : return true;
234 : }
235 : }
236 18716 : return false;
237 : }
238 :
239 44958 : const bool LoadBalance::IsDefault() const {
240 44958 : 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 : }
|