Line data Source code
1 : /*
2 : * Copyright (c) 2014-2024 Juniper Networks, Inc. All rights reserved.
3 : * Copyright (c) 2024 Elena Zizganova
4 : */
5 :
6 : #include <boost/uuid/uuid_io.hpp>
7 : #include <boost/lexical_cast.hpp>
8 :
9 : #include <cmn/agent_cmn.h>
10 : #include <route/route.h>
11 :
12 : #include <cmn/agent_cmn.h>
13 : #include <oper/ecmp_load_balance.h>
14 : #include <oper/ecmp.h>
15 : #include <oper/route_common.h>
16 : #include <oper/vrf.h>
17 : #include <oper/tunnel_nh.h>
18 : #include <oper/mpls.h>
19 : #include <oper/mirror_table.h>
20 : #include <oper/peer.h>
21 : #include <oper/agent_route.h>
22 : #include <controller/controller_route_path.h>
23 : #include <controller/controller_peer.h>
24 : #include <controller/controller_init.h>
25 : #include <controller/controller_export.h>
26 : #include <controller/controller_types.h>
27 : #include <oper/vxlan_routing_manager.h>
28 : #include <oper/agent_sandesh.h>
29 : #include <xmpp/xmpp_channel.h>
30 : #include <xmpp_enet_types.h>
31 : #include <xmpp_unicast_types.h>
32 :
33 : using namespace std;
34 : using namespace boost::asio;
35 :
36 19 : ControllerPeerPath::ControllerPeerPath(const BgpPeer *peer) :
37 19 : AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0), peer_(peer) {
38 19 : sequence_number_ = 0;
39 19 : if (peer)
40 19 : sequence_number_ = peer->GetAgentXmppChannel()->
41 19 : sequence_number();
42 19 : }
43 :
44 1 : bool ControllerEcmpRoute::CopyToPath(AgentPath *path) {
45 1 : bool ret = false;
46 :
47 1 : path->set_peer_sequence_number(sequence_number());
48 1 : if (path->ecmp_load_balance() != ecmp_load_balance_) {
49 0 : path->UpdateEcmpHashFields(agent_, ecmp_load_balance_,
50 0 : nh_req_);
51 0 : ret = true;
52 : }
53 :
54 1 : return ret;
55 : }
56 :
57 1 : bool ControllerEcmpRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
58 : const AgentRoute *rt) {
59 1 : bool path_unresolved = false;
60 1 : path->set_copy_local_path(copy_local_path_);
61 :
62 : // check if tunnel type is mpls and vrf is non default
63 1 : if ((tunnel_bmap_ == (1 << TunnelType::MPLS_OVER_MPLS)) &&
64 0 : (vrf_name_ != agent->fabric_vrf_name())) {
65 :
66 : // this path depends on inet.3 route table,
67 : // update dependent_table if it is not set already.
68 0 : if (!path->GetDependentTable()) {
69 0 : InetUnicastAgentRouteTable *table = NULL;
70 : table = static_cast<InetUnicastAgentRouteTable *>
71 0 : (agent->fabric_inet4_mpls_table());
72 0 : assert(table != NULL);
73 0 : path->SetDependentTable(table);
74 : }
75 : InetUnicastAgentRouteTable *table =
76 0 : (InetUnicastAgentRouteTable *)path->GetDependentTable();
77 0 : assert(table != NULL);
78 0 : AgentPathEcmpComponentPtrList new_list;
79 0 : ComponentNHKeyList comp_nh_list;
80 0 : bool comp_nh_policy = false;
81 0 : for (uint32_t i = 0; i < tunnel_dest_list_.size(); i++) {
82 : // step1: update ecmpcomponent list
83 0 : IpAddress addr = tunnel_dest_list_[i];
84 0 : uint32_t label = label_list_[i];
85 : AgentPathEcmpComponentPtr member(new AgentPathEcmpComponent(
86 0 : addr, label, path->GetParentRoute()));
87 0 : InetUnicastRouteEntry *uc_rt = table->FindRoute(addr);
88 : const NextHop *anh;
89 0 : if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
90 0 : member->SetUnresolved(true);
91 0 : if (!path_unresolved) {
92 0 : path_unresolved = true;
93 : DBEntryBase::KeyPtr key =
94 0 : agent->nexthop_table()->discard_nh()->GetDBRequestKey();
95 : NextHopKey *nh_key =
96 0 : static_cast<NextHopKey *>(key.release());
97 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
98 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
99 0 : std::move(nh_key_ptr)));
100 0 : comp_nh_list.push_back(component_nh_key);
101 0 : }
102 : } else {
103 : DBEntryBase::KeyPtr key =
104 0 : anh->GetDBRequestKey();
105 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
106 0 : if (nh_key->GetType() != NextHop::COMPOSITE) {
107 : //By default all component members of composite NH
108 : //will be policy disabled, except for component NH
109 : //of type composite
110 0 : nh_key->SetPolicy(false);
111 : }
112 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
113 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
114 0 : std::move(nh_key_ptr)));
115 0 : comp_nh_list.push_back(component_nh_key);
116 : //Reset to new gateway route, no nexthop for indirect route
117 0 : member->UpdateDependentRoute(uc_rt);
118 0 : member->SetUnresolved(false);
119 0 : }
120 0 : new_list.push_back(member);
121 0 : }
122 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
123 0 : nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy,
124 0 : comp_nh_list, vrf_name_));
125 0 : nh_req.data.reset(new CompositeNHData());
126 0 : nh_req_.Swap(&nh_req);
127 0 : path->ResetEcmpMemberList(new_list);
128 0 : }
129 1 : path->set_vrf_name(vrf_name_);
130 :
131 1 : CompositeNHKey *comp_key = static_cast<CompositeNHKey *>(nh_req_.key.get());
132 1 : bool ret = false;
133 :
134 1 : if (tunnel_bmap_ == TunnelType::VxlanType() && vxlan_id_ != 0) {
135 0 : path->set_vxlan_id(vxlan_id_);
136 : }
137 :
138 : //Reorder the component NH list, and add a reference to local composite mpls
139 : //label if any
140 1 : bool comp_nh_policy = comp_key->GetPolicy();
141 1 : bool new_comp_nh_policy = false;
142 3 : if (path->ReorderCompositeNH(agent, comp_key, new_comp_nh_policy,
143 1 : rt->FindLocalVmPortPath()) == false) {
144 0 : return false;
145 : }
146 1 : if (!comp_nh_policy) {
147 1 : comp_key->SetPolicy(new_comp_nh_policy);
148 : }
149 1 : ret |= CopyToPath(path);
150 :
151 1 : EcmpData ecmp_data(agent, rt->vrf()->GetName(), rt->ToString(),
152 1 : path, false);
153 1 : ret |= ecmp_data.UpdateWithParams(sg_list_, tag_list_, CommunityList(),
154 1 : path_preference_, tunnel_bmap_,
155 1 : ecmp_load_balance_, vn_list_, nh_req_);
156 1 : path->set_unresolved(path_unresolved);
157 :
158 : // Set dest vn
159 1 : path->set_dest_vn_list(vn_list_);
160 :
161 1 : return ret;
162 1 : }
163 :
164 : template <typename TYPE>
165 0 : ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
166 : const VnListType &vn_list,
167 : const EcmpLoadBalance &ecmp_load_balance,
168 : const TagList &tag_list,
169 : const TYPE *item,
170 : const AgentRouteTable *rt_table,
171 : const std::string &prefix_str) :
172 0 : ControllerPeerPath(peer), vn_list_(vn_list),
173 0 : ecmp_load_balance_(ecmp_load_balance), tag_list_(tag_list),
174 0 : copy_local_path_(false), vxlan_id_(0) {
175 0 : const AgentXmppChannel *channel = peer->GetAgentXmppChannel();
176 0 : std::string bgp_peer_name = channel->GetBgpPeerName();
177 0 : std::string vrf_name = rt_table->vrf_name();
178 0 : agent_ = rt_table->agent();
179 0 : vrf_name_ = vrf_name;
180 0 : uint32_t label = item->entry.next_hops.next_hop[0].label;
181 0 : Composite::Type composite_nh_type = Composite::ECMP;
182 :
183 : // use LOW PathPreference if local preference attribute is not set
184 0 : uint32_t preference = PathPreference::LOW;
185 0 : TunnelType::TypeBmap encap = TunnelType::AllType(); //default
186 0 : if (item->entry.local_preference != 0) {
187 0 : preference = item->entry.local_preference;
188 : }
189 :
190 : //Override encap type for fabric VRF routes
191 : //only type supported is underlay
192 0 : if (vrf_name == agent_->fabric_vrf_name()) {
193 0 : encap = TunnelType::NativeType();
194 : }
195 :
196 0 : const bool is_routing_vrf = VxlanRoutingManager::IsVxlanAvailable(agent_)
197 0 : && VxlanRoutingManager::IsRoutingVrf(vrf_name, agent_);
198 : // Override encap type for routing VRF routes
199 0 : if (is_routing_vrf) {
200 0 : encap = TunnelType::VxlanType();
201 0 : vxlan_id_ = label;
202 : }
203 :
204 0 : std::vector<std::string> peer_sources;
205 0 : for (const auto &peer_addr : item->entry.peers.peer) {
206 0 : peer_sources.push_back(peer_addr);
207 : }
208 :
209 0 : PathPreference rp(item->entry.sequence_number, preference, false, false);
210 0 : path_preference_ = rp;
211 :
212 0 : sg_list_ = item->entry.security_group_list.security_group;
213 :
214 0 : ComponentNHKeyList comp_nh_list;
215 0 : bool intf_exist = false;
216 0 : bool tun_exist = false;
217 0 : bool comp_nh_policy = false;
218 0 : for (uint32_t i = 0; i < item->entry.next_hops.next_hop.size(); i++) {
219 0 : std::string nexthop_addr =
220 0 : item->entry.next_hops.next_hop[i].address;
221 0 : boost::system::error_code ec;
222 0 : IpAddress addr = IpAddress::from_string(nexthop_addr, ec);
223 0 : if (ec.value() != 0) {
224 0 : CONTROLLER_TRACE(Trace, bgp_peer_name, vrf_name,
225 : "Error parsing nexthop ip address");
226 0 : continue;
227 : }
228 0 : if (!addr.is_v4()) {
229 0 : CONTROLLER_TRACE(Trace, bgp_peer_name, vrf_name,
230 : "Non IPv4 address not supported as nexthop");
231 0 : continue;
232 : }
233 :
234 0 : if (comp_nh_list.size() >= maximum_ecmp_paths) {
235 0 : std::stringstream msg;
236 : msg << "Nexthop paths for prefix "
237 : << prefix_str
238 0 : << " (" << item->entry.next_hops.next_hop.size()
239 0 : << ") exceed the maximum supported, ignoring them";
240 0 : CONTROLLER_TRACE(Trace, bgp_peer_name, vrf_name, msg.str());
241 0 : break;
242 0 : }
243 :
244 0 : uint32_t label = item->entry.next_hops.next_hop[i].label;
245 0 : if (agent_->router_id() == addr.to_v4()) {
246 0 : encap = agent_->controller()->GetTypeBitmap
247 0 : (item->entry.next_hops.next_hop[i].tunnel_encapsulation_list);
248 : //Get local list of interface and append to the list
249 : MplsLabel *mpls =
250 0 : agent_->mpls_table()->FindMplsLabel(label);
251 0 : if (mpls != NULL && !is_routing_vrf) {
252 0 : if (mpls->nexthop()->GetType() == NextHop::VRF) {
253 0 : ClonedLocalPath *data =
254 0 : new ClonedLocalPath(label, vn_list,
255 0 : item->entry.security_group_list.security_group,
256 0 : tag_list, sequence_number());
257 0 : cloned_data_list_.push_back(data);
258 0 : continue;
259 0 : }
260 :
261 0 : const NextHop *mpls_nh = mpls->nexthop();
262 0 : DBEntryBase::KeyPtr key = mpls_nh->GetDBRequestKey();
263 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
264 0 : if (nh_key->GetType() != NextHop::COMPOSITE) {
265 : //By default all component members of composite NH
266 : //will be policy disabled, except for component NH
267 : //of type composite
268 0 : nh_key->SetPolicy(false);
269 : }
270 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
271 0 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
272 0 : std::move(nh_key_ptr)));
273 0 : comp_nh_list.push_back(component_nh_key);
274 0 : if (!comp_nh_policy) {
275 0 : comp_nh_policy = mpls_nh->NexthopToInterfacePolicy();
276 : }
277 0 : tunnel_dest_list_.push_back(addr);
278 0 : label_list_.push_back(label);
279 0 : } else {
280 0 : if (label == 0) {
281 0 : copy_local_path_ = true;
282 : }
283 0 : if (is_routing_vrf) {
284 0 : encap = TunnelType::VxlanType();
285 0 : VxlanRoutingManager::AddInterfaceComponentToList(item->entry.nlri.address,
286 : vrf_name,
287 0 : item->entry.next_hops.next_hop[i],
288 : comp_nh_list,
289 : peer_sources);
290 0 : intf_exist = true;
291 : }
292 : }
293 : } else {
294 0 : encap = agent_->controller()->GetTypeBitmap
295 0 : (item->entry.next_hops.next_hop[i].tunnel_encapsulation_list);
296 0 : if (is_routing_vrf){
297 0 : encap = TunnelType::VxlanType();
298 : }
299 0 : if (vrf_name == agent_->fabric_vrf_name()) {
300 0 : if (label != MplsTable::kInvalidLabel &&
301 0 : label != MplsTable::kInvalidExportLabel) {
302 0 : encap = TunnelType::MplsoMplsType();
303 : } else {
304 0 : encap = TunnelType::NativeType();
305 : }
306 : }
307 0 : MacAddress mac = agent_->controller()->GetTunnelMac
308 0 : (item->entry.next_hops.next_hop[i]);
309 0 : if (encap == TunnelType::MplsoMplsType() &&
310 0 : vrf_name == agent_->fabric_vrf_name()) {
311 0 : composite_nh_type = Composite::LU_ECMP;
312 0 : LabelledTunnelNHKey *nh_key = new LabelledTunnelNHKey(
313 0 : agent_->fabric_vrf_name(),
314 0 : agent_->router_id(),
315 : addr.to_v4(),
316 : false,
317 : TunnelType::ComputeType(encap),
318 : mac,
319 : label);
320 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
321 0 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
322 0 : std::move(nh_key_ptr)));
323 0 : comp_nh_list.push_back(component_nh_key);
324 0 : } else if (encap == TunnelType::MplsoMplsType()) {
325 : // copy ecmp nexthop list
326 0 : tunnel_dest_list_.push_back(addr);
327 0 : label_list_.push_back(label);
328 : } else {
329 0 : TunnelNHKey *nh_key = NULL;
330 0 : if (is_routing_vrf) {
331 0 : nh_key = agent_->oper_db()->vxlan_routing_manager()->
332 0 : AllocateTunnelNextHopKey(addr, mac);
333 0 : tun_exist = true;
334 : } else {
335 0 : nh_key = new TunnelNHKey(agent_->fabric_vrf_name(),
336 0 : agent_->router_id(),
337 : addr.to_v4(),
338 : false,
339 : TunnelType::ComputeType(encap),
340 : mac);
341 : }
342 :
343 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
344 0 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
345 0 : std::move(nh_key_ptr)));
346 0 : comp_nh_list.push_back(component_nh_key);
347 0 : }
348 : }
349 : }
350 :
351 0 : if (intf_exist && tun_exist) {
352 0 : for (auto &comp_nh_ptr : comp_nh_list) {
353 0 : if (comp_nh_ptr == nullptr) {
354 0 : continue;
355 : }
356 0 : if (comp_nh_ptr->nh_key()->GetType() != NextHop::INTERFACE)
357 : {
358 0 : comp_nh_ptr.reset();
359 : }
360 : }
361 : }
362 0 : if (intf_exist) {
363 0 : comp_nh_policy = true;
364 0 : composite_nh_type = Composite::LOCAL_ECMP;
365 : }
366 :
367 0 : tunnel_bmap_ = encap;
368 0 : if ((encap != TunnelType::MplsoMplsType()) ||
369 0 : ((encap == TunnelType::MplsoMplsType()) &&
370 0 : (vrf_name_ == agent_->fabric_vrf_name()))) {
371 : // Build the NH request and then create route data to be passed
372 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
373 0 : nh_req.key.reset(new CompositeNHKey(composite_nh_type, comp_nh_policy,
374 : comp_nh_list, vrf_name));
375 0 : nh_req.data.reset(new CompositeNHData());
376 0 : nh_req_.Swap(&nh_req);
377 0 : }
378 0 : }
379 :
380 1 : ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
381 : const VnListType &vn_list,
382 : const EcmpLoadBalance &ecmp_load_balance,
383 : const TagList &tag_list,
384 : const SecurityGroupList &sg_list,
385 : const PathPreference &path_pref,
386 : TunnelType::TypeBmap tunnel_bmap,
387 : DBRequest &nh_req,
388 : const std::string &prefix_str,
389 1 : const std::string vrf_name) :
390 1 : ControllerPeerPath(peer), vn_list_(vn_list), sg_list_(sg_list),
391 1 : ecmp_load_balance_(ecmp_load_balance), tag_list_(tag_list),
392 1 : path_preference_(path_pref), tunnel_bmap_(tunnel_bmap),
393 2 : copy_local_path_(false), vxlan_id_(0) {
394 1 : nh_req_.Swap(&nh_req);
395 1 : agent_ = peer->agent();
396 1 : if (vrf_name.size() == 0) {
397 1 : vrf_name_ = agent_->fabric_vrf_name();
398 : } else {
399 0 : vrf_name_ = vrf_name;
400 : }
401 3 : const bool is_routing_vrf = VxlanRoutingManager::IsVxlanAvailable(agent_) && VxlanRoutingManager::IsRoutingVrf(vrf_name,
402 2 : agent_);
403 1 : if (is_routing_vrf || tunnel_bmap == TunnelType::VxlanType()) {
404 0 : tunnel_bmap_ = TunnelType::VxlanType();
405 0 : vxlan_id_ = agent_->vrf_table()->
406 0 : FindVrfFromName(vrf_name)->vxlan_id();
407 : }
408 1 : }
409 :
410 0 : ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
411 : const VnListType &vn_list,
412 : const EcmpLoadBalance &ecmp_load_balance,
413 : const TagList &tag_list,
414 : const SecurityGroupList &sg_list,
415 : const PathPreference &path_pref,
416 : TunnelType::TypeBmap tunnel_bmap,
417 : std::vector<IpAddress> &tunnel_dest_list,
418 : std::vector<uint32_t> &label_list,
419 : const std::string &prefix_str,
420 0 : const std::string &vrf_name):
421 0 : ControllerPeerPath(peer), vn_list_(vn_list), sg_list_(sg_list),
422 0 : ecmp_load_balance_(ecmp_load_balance), tag_list_(tag_list),
423 0 : path_preference_(path_pref), tunnel_bmap_(tunnel_bmap),
424 0 : copy_local_path_(false), tunnel_dest_list_(tunnel_dest_list),
425 0 : label_list_(label_list), vrf_name_(vrf_name), vxlan_id_(0) {
426 0 : agent_ = peer->agent();
427 0 : }
428 :
429 9 : ControllerVmRoute *ControllerVmRoute::MakeControllerVmRoute(
430 : const BgpPeer *bgp_peer,
431 : const string &default_vrf,
432 : const Ip4Address &router_id,
433 : const string &vrf_name,
434 : const Ip4Address &tunnel_dest,
435 : TunnelType::TypeBmap bmap,
436 : uint32_t label,
437 : const MacAddress rewrite_dmac,
438 : const VnListType &dest_vn_list,
439 : const SecurityGroupList &sg_list,
440 : const TagList &tag_list,
441 : const PathPreference &path_preference,
442 : bool ecmp_suppressed,
443 : const EcmpLoadBalance &ecmp_load_balance,
444 : bool etree_leaf) {
445 :
446 9 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
447 : // Make Tunnel-NH request
448 18 : nh_req.key.reset(new TunnelNHKey(default_vrf, router_id, tunnel_dest, false,
449 : TunnelType::ComputeType(bmap),
450 9 : rewrite_dmac));
451 9 : nh_req.data.reset(new TunnelNHData());
452 :
453 : // Make route request pointing to Tunnel-NH created above
454 : ControllerVmRoute *data =
455 : new ControllerVmRoute(bgp_peer, default_vrf, tunnel_dest, label,
456 : dest_vn_list, bmap, sg_list, tag_list, path_preference,
457 : nh_req, ecmp_suppressed,
458 9 : ecmp_load_balance, etree_leaf, rewrite_dmac);
459 9 : return data;
460 9 : }
461 :
462 0 : ControllerMplsRoute *ControllerMplsRoute::MakeControllerMplsRoute(
463 : const BgpPeer *bgp_peer,
464 : const string &default_vrf,
465 : const Ip4Address &router_id,
466 : const string &vrf_name,
467 : const Ip4Address &tunnel_dest,
468 : TunnelType::TypeBmap bmap,
469 : uint32_t label,
470 : const MacAddress rewrite_dmac,
471 : const VnListType &dest_vn_list,
472 : const SecurityGroupList &sg_list,
473 : const TagList &tag_list,
474 : const PathPreference &path_preference,
475 : bool ecmp_suppressed,
476 : const EcmpLoadBalance &ecmp_load_balance,
477 : bool etree_leaf) {
478 :
479 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
480 : // Make Labelled Tunnel-NH request
481 0 : nh_req.key.reset(new LabelledTunnelNHKey(default_vrf, router_id, tunnel_dest, false,
482 : TunnelType::MPLS_OVER_MPLS,
483 0 : rewrite_dmac, label));
484 0 : nh_req.data.reset(new LabelledTunnelNHData());
485 :
486 : // Make route request pointing to Labelled Tunnel-NH created above
487 : ControllerMplsRoute *data =
488 : new ControllerMplsRoute(bgp_peer, default_vrf, tunnel_dest, label,
489 : dest_vn_list, bmap, sg_list, tag_list, path_preference,
490 : nh_req, ecmp_suppressed,
491 0 : ecmp_load_balance, etree_leaf, rewrite_dmac);
492 0 : return data;
493 0 : }
494 9 : bool ControllerVmRoute::UpdateRoute(AgentRoute *rt) {
495 9 : bool ret = false;
496 : // For IP subnet routes with Tunnel NH, update arp_flood_ and
497 : // local_host_flag_ flags
498 15 : if ((rt->GetTableType() == Agent::INET4_UNICAST) ||
499 6 : (rt->GetTableType() == Agent::INET6_UNICAST)) {
500 3 : InetUnicastRouteEntry *inet_rt =
501 : static_cast<InetUnicastRouteEntry *>(rt);
502 : //If its the IPAM route then no change required neither
503 : //super net needs to be searched.
504 3 : if (inet_rt->ipam_subnet_route())
505 0 : return ret;
506 :
507 3 : bool ipam_subnet_route = inet_rt->IpamSubnetRouteAvailable();
508 3 : ret = inet_rt->UpdateIpamHostFlags(ipam_subnet_route);
509 : }
510 9 : return ret;
511 : }
512 :
513 9 : bool ControllerVmRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
514 : const AgentRoute *rt) {
515 9 : bool ret = false;
516 9 : NextHop *nh = NULL;
517 9 : SecurityGroupList path_sg_list;
518 :
519 9 : path->set_peer_sequence_number(sequence_number());
520 9 : if (path->tunnel_bmap() != tunnel_bmap_) {
521 8 : path->set_tunnel_bmap(tunnel_bmap_);
522 8 : ret = true;
523 : }
524 :
525 9 : TunnelType::Type new_tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
526 9 : if (new_tunnel_type == TunnelType::MPLS_OVER_MPLS) {
527 : // this path depends on inet.3 route table,
528 : // update dependent_table if it is not set already.
529 0 : if (!path->GetDependentTable()) {
530 0 : InetUnicastAgentRouteTable *table = NULL;
531 : table = static_cast<InetUnicastAgentRouteTable *>
532 0 : (agent->fabric_inet4_mpls_table());
533 0 : assert(table != NULL);
534 0 : path->SetDependentTable(table);
535 : }
536 : InetUnicastAgentRouteTable *table =
537 0 : (InetUnicastAgentRouteTable *)path->GetDependentTable();
538 :
539 0 : AgentPathEcmpComponentPtrList new_list;
540 : AgentPathEcmpComponentPtr member( new AgentPathEcmpComponent(
541 0 : tunnel_dest_, label_,
542 0 : path->GetParentRoute()));
543 0 : InetUnicastRouteEntry *uc_rt = table->FindRoute(tunnel_dest_);
544 : const NextHop *anh;
545 0 : if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
546 0 : path->set_unresolved(true);
547 0 : member->SetUnresolved(false);
548 : } else {
549 0 : path->set_unresolved(false);
550 0 : DBEntryBase::KeyPtr key = anh->GetDBRequestKey();
551 : const NextHopKey *nh_key =
552 0 : static_cast<const NextHopKey*>(key.get());
553 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
554 0 : FindActiveEntry(nh_key));
555 0 : assert(nh !=NULL);
556 : //Reset to new gateway route, no nexthop for indirect route
557 0 : member->UpdateDependentRoute(uc_rt);
558 0 : member->SetUnresolved(false);
559 0 : path->set_gw_ip(tunnel_dest_);
560 0 : path->set_nexthop(NULL);
561 0 : }
562 0 : new_list.push_back(member);
563 0 : path->ResetEcmpMemberList(new_list);
564 :
565 0 : } else {
566 :
567 9 : if ((tunnel_bmap_ == (1 << TunnelType::VXLAN) &&
568 9 : (new_tunnel_type != TunnelType::VXLAN)) ||
569 9 : (tunnel_bmap_ != (1 << TunnelType::VXLAN) &&
570 : (new_tunnel_type == TunnelType::VXLAN))) {
571 0 : new_tunnel_type = TunnelType::INVALID;
572 0 : nh_req_.key.reset(new TunnelNHKey(agent->fabric_vrf_name(),
573 0 : agent->router_id(), tunnel_dest_,
574 : false, new_tunnel_type,
575 0 : rewrite_dmac_));
576 : }
577 9 : agent->nexthop_table()->Process(nh_req_);
578 18 : TunnelNHKey key(agent->fabric_vrf_name(), agent->router_id(), tunnel_dest_,
579 18 : false, new_tunnel_type, rewrite_dmac_);
580 9 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
581 :
582 9 : path->set_unresolved(false);
583 9 : }
584 9 : path->set_tunnel_dest(tunnel_dest_);
585 :
586 9 : if (path->tunnel_type() != new_tunnel_type) {
587 5 : path->set_tunnel_type(new_tunnel_type);
588 5 : ret = true;
589 : }
590 :
591 : //Interpret label sent by control node
592 9 : if (tunnel_bmap_ == TunnelType::VxlanType()) {
593 : // Only VXLAN encap is sent, so label is VXLAN
594 : // For vxlan routing vn external route label can change , add path change
595 16 : if (rt->vrf() && rt->vrf()->vn() &&
596 16 : rt->vrf()->vn()->vxlan_routing_vn() && path->vxlan_id() != label_) {
597 0 : ret = true;
598 : }
599 6 : path->set_vxlan_id(label_);
600 6 : if (path->label() != MplsTable::kInvalidLabel) {
601 0 : path->set_label(MplsTable::kInvalidLabel);
602 0 : ret = true;
603 : }
604 6 : } else if ((tunnel_bmap_ == TunnelType::MplsType())||
605 3 : (tunnel_bmap_ == TunnelType::MplsoMplsType())) {
606 : //MPLS (GRE/UDP) is the only encap sent,
607 : //so label is MPLS.
608 0 : if (path->label() != label_) {
609 0 : path->set_label(label_);
610 0 : ret = true;
611 : }
612 0 : path->set_vxlan_id(VxLanTable::kInvalidvxlan_id);
613 : } else {
614 : //Got a mix of Vxlan and Mpls, so interpret label
615 : //as per the computed tunnel type.
616 3 : if (new_tunnel_type == TunnelType::VXLAN) {
617 0 : if (path->vxlan_id() != label_) {
618 0 : path->set_vxlan_id(label_);
619 0 : path->set_label(MplsTable::kInvalidLabel);
620 0 : ret = true;
621 : }
622 : } else {
623 3 : if (path->label() != label_) {
624 3 : path->set_label(label_);
625 3 : path->set_vxlan_id(VxLanTable::kInvalidvxlan_id);
626 3 : ret = true;
627 : }
628 : }
629 : }
630 :
631 9 : if (path->dest_vn_list() != dest_vn_list_) {
632 8 : path->set_dest_vn_list(dest_vn_list_);
633 8 : ret = true;
634 : }
635 :
636 9 : if (nh != NULL) {
637 9 : if (path->ChangeNH(agent, nh) == true)
638 8 : ret = true;
639 : }
640 :
641 9 : path_sg_list = path->sg_list();
642 9 : if (path_sg_list != sg_list_) {
643 9 : path->set_sg_list(sg_list_);
644 9 : ret = true;
645 : }
646 :
647 9 : if (tag_list_ != path->tag_list()) {
648 0 : path->set_tag_list(tag_list_);
649 0 : ret = true;
650 : }
651 :
652 9 : if (path->path_preference() != path_preference_) {
653 0 : path->set_path_preference(path_preference_);
654 0 : ret = true;
655 : }
656 :
657 : //If a transition of path happens from ECMP to non ECMP
658 : //reset local mpls label reference and composite nh key
659 9 : if (path->composite_nh_key()) {
660 0 : path->set_composite_nh_key(NULL);
661 0 : path->set_local_ecmp_mpls_label(NULL);
662 : }
663 :
664 9 : if (path->ecmp_suppressed() != ecmp_suppressed_) {
665 0 : path->set_ecmp_suppressed(ecmp_suppressed_);
666 0 : ret = true;
667 : }
668 :
669 9 : if (ecmp_load_balance_ != path->ecmp_load_balance()) {
670 0 : path->set_ecmp_load_balance(ecmp_load_balance_);
671 0 : ret = true;
672 : }
673 :
674 9 : if (path->etree_leaf() != etree_leaf_) {
675 0 : path->set_etree_leaf(etree_leaf_);
676 0 : ret = true;
677 : }
678 :
679 9 : return ret;
680 9 : }
681 0 : bool ControllerMplsRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
682 : const AgentRoute *rt) {
683 0 : bool ret = false;
684 0 : NextHop *nh = NULL;
685 0 : SecurityGroupList path_sg_list;
686 :
687 0 : path->set_peer_sequence_number(sequence_number());
688 0 : if (path->tunnel_bmap() != tunnel_bmap_) {
689 0 : path->set_tunnel_bmap(tunnel_bmap_);
690 0 : ret = true;
691 : }
692 :
693 0 : agent->nexthop_table()->Process(nh_req_);
694 0 : LabelledTunnelNHKey key(agent->fabric_vrf_name(), agent->router_id(), tunnel_dest_,
695 0 : false, TunnelType::MPLS_OVER_MPLS, rewrite_dmac_, label_);
696 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
697 0 : path->set_tunnel_dest(tunnel_dest_);
698 :
699 0 : if (path->label() != label_) {
700 0 : path->set_label(label_);
701 0 : ret = true;
702 : }
703 :
704 0 : if (path->dest_vn_list() != dest_vn_list_) {
705 0 : path->set_dest_vn_list(dest_vn_list_);
706 0 : ret = true;
707 : }
708 :
709 0 : path->set_unresolved(false);
710 0 : if (path->ChangeNH(agent, nh) == true)
711 0 : ret = true;
712 :
713 0 : path_sg_list = path->sg_list();
714 0 : if (path_sg_list != sg_list_) {
715 0 : path->set_sg_list(sg_list_);
716 0 : ret = true;
717 : }
718 :
719 0 : if (tag_list_ != path->tag_list()) {
720 0 : path->set_tag_list(tag_list_);
721 0 : ret = true;
722 : }
723 :
724 0 : if (path->path_preference() != path_preference_) {
725 0 : path->set_path_preference(path_preference_);
726 0 : ret = true;
727 : }
728 :
729 : //If a transition of path happens from ECMP to non ECMP
730 : //reset local mpls label reference and composite nh key
731 0 : if (path->composite_nh_key()) {
732 0 : path->set_composite_nh_key(NULL);
733 0 : path->set_local_ecmp_mpls_label(NULL);
734 : }
735 :
736 0 : if (path->ecmp_suppressed() != ecmp_suppressed_) {
737 0 : path->set_ecmp_suppressed(ecmp_suppressed_);
738 0 : ret = true;
739 : }
740 :
741 0 : if (ecmp_load_balance_ != path->ecmp_load_balance()) {
742 0 : path->set_ecmp_load_balance(ecmp_load_balance_);
743 0 : ret = true;
744 : }
745 :
746 0 : if (path->etree_leaf() != etree_leaf_) {
747 0 : path->set_etree_leaf(etree_leaf_);
748 0 : ret = true;
749 : }
750 :
751 0 : return ret;
752 0 : }
753 :
754 0 : bool ClonedLocalPath::AddChangePathExtended(Agent *agent, AgentPath *path,
755 : const AgentRoute *rt) {
756 0 : bool ret = false;
757 :
758 0 : AgentPath *local_path = NULL;
759 0 : if (mpls_label_ == MplsTable::kInvalidExportLabel) {
760 0 : local_path = rt->FindPath(agent->fabric_rt_export_peer());
761 0 : if (local_path == NULL) {
762 0 : local_path = rt->FindLocalVmPortPath();
763 : }
764 0 : path->set_copy_local_path(true);
765 : } else {
766 0 : MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(mpls_label_);
767 0 : if (!mpls) {
768 0 : return ret;
769 : }
770 :
771 0 : assert(mpls->nexthop()->GetType() == NextHop::VRF);
772 0 : const VrfNH *vrf_nh = static_cast<const VrfNH *>(mpls->nexthop());
773 0 : const InetUnicastRouteEntry *uc_rt =
774 : static_cast<const InetUnicastRouteEntry *>(rt);
775 : const AgentRoute *mpls_vrf_uc_rt =
776 0 : vrf_nh->GetVrf()->GetUcRoute(uc_rt->prefix_address());
777 0 : if (mpls_vrf_uc_rt == NULL) {
778 0 : return ret;
779 : }
780 0 : local_path = mpls_vrf_uc_rt->FindLocalVmPortPath();
781 : }
782 :
783 0 : path->set_peer_sequence_number(sequence_number_);
784 :
785 0 : if (!local_path) {
786 0 : return ret;
787 : }
788 :
789 0 : if (path->dest_vn_list() != vn_list_) {
790 0 : path->set_dest_vn_list(vn_list_);
791 0 : ret = true;
792 : }
793 0 : path->set_unresolved(false);
794 :
795 0 : if (path->sg_list() != sg_list_) {
796 0 : path->set_sg_list(sg_list_);
797 0 : ret = true;
798 : }
799 :
800 0 : path->set_tunnel_bmap(local_path->tunnel_bmap());
801 : TunnelType::Type new_tunnel_type =
802 0 : TunnelType::ComputeType(path->tunnel_bmap());
803 0 : if (new_tunnel_type == TunnelType::VXLAN &&
804 0 : local_path->vxlan_id() == VxLanTable::kInvalidvxlan_id) {
805 0 : new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
806 : }
807 :
808 0 : if (path->tunnel_type() != new_tunnel_type) {
809 0 : path->set_tunnel_type(new_tunnel_type);
810 0 : ret = true;
811 : }
812 :
813 : // If policy force-enabled in request, enable policy
814 0 : path->set_force_policy(local_path->force_policy());
815 :
816 0 : if (path->label() != local_path->label()) {
817 0 : path->set_label(local_path->label());
818 0 : ret = true;
819 : }
820 :
821 0 : if (path->vxlan_id() != local_path->vxlan_id()) {
822 0 : path->set_vxlan_id(local_path->vxlan_id());
823 0 : ret = true;
824 : }
825 :
826 0 : if (path->path_preference() != local_path->path_preference()) {
827 0 : path->set_path_preference(local_path->path_preference());
828 0 : ret = true;
829 : }
830 :
831 0 : NextHop *nh = const_cast<NextHop *>(local_path->ComputeNextHop(agent));
832 0 : if (path->ChangeNH(agent, nh) == true) {
833 0 : ret = true;
834 : }
835 0 : DBEntryBase::KeyPtr key = nh->GetDBRequestKey();
836 0 : CompositeNHKey *nh_key = dynamic_cast<CompositeNHKey *>(key.release());
837 0 : path->set_composite_nh_key(nh_key);
838 :
839 0 : return ret;
840 0 : }
841 :
842 0 : bool StalePathData::AddChangePathExtended(Agent *agent, AgentPath *path,
843 : const AgentRoute *route) {
844 0 : if (path->peer_sequence_number() >= sequence_number_)
845 0 : return false;
846 :
847 0 : if (route->IsDeleted())
848 0 : return false;
849 :
850 : //Delete old stale path
851 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
852 : AgentRouteKey *key = (static_cast<AgentRouteKey *>(route->
853 0 : GetDBRequestKey().get()))->Clone();
854 0 : key->set_peer(path->peer());
855 0 : req.key.reset(key);
856 0 : req.data.reset();
857 0 : AgentRouteTable *table = static_cast<AgentRouteTable *>(route->get_table());
858 0 : table->Process(req);
859 0 : return true;
860 0 : }
861 :
862 0 : bool StalePathData::CanDeletePath(Agent *agent, AgentPath *path,
863 : const AgentRoute *route) const {
864 0 : if (path->peer_sequence_number() >= sequence_number_)
865 0 : return false;
866 0 : return true;
867 : }
868 :
869 : //Force instantiation
870 : template ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
871 : const VnListType &vn_list,
872 : const EcmpLoadBalance &ecmp_load_balance,
873 : const TagList &tag_list, const autogen::ItemType *item,
874 : const AgentRouteTable *rt_table, const std::string &prefix_str);
875 : template ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
876 : const VnListType &vn_list,
877 : const EcmpLoadBalance &ecmp_load_balance,
878 : const TagList &tag_list, const autogen::EnetItemType *item,
879 : const AgentRouteTable *rt_table, const std::string &prefix_str);
|