Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <boost/uuid/uuid_io.hpp>
7 : #include <boost/lexical_cast.hpp>
8 : #include <boost/foreach.hpp>
9 : #include <cmn/agent_cmn.h>
10 : #include <route/route.h>
11 : #include <init/agent_param.h>
12 :
13 : #include <vnc_cfg_types.h>
14 : #include <agent_types.h>
15 :
16 : #include <filter/acl.h>
17 :
18 : #include <oper/peer.h>
19 : #include <oper/vrf.h>
20 : #include <oper/interface_common.h>
21 : #include <oper/nexthop.h>
22 : #include <oper/tunnel_nh.h>
23 : #include <oper/vn.h>
24 : #include <oper/mirror_table.h>
25 : #include <oper/vxlan.h>
26 : #include <oper/mpls.h>
27 : #include <oper/route_common.h>
28 : #include <oper/ecmp_load_balance.h>
29 : #include <oper/agent_sandesh.h>
30 : #include <oper/tsn_elector.h>
31 :
32 : using namespace std;
33 : using namespace boost::asio;
34 :
35 : //Helpers
36 2408 : bool RebakeLabel(MplsTable *table, uint32_t label, NextHop *nh) {
37 2408 : bool ret = false;
38 2408 : if (label != MplsTable::kInvalidLabel) {
39 2278 : MplsLabelKey key(label);
40 2278 : MplsLabel *mpls = static_cast<MplsLabel *>(table->
41 2278 : FindActiveEntry(&key));
42 2278 : if (mpls && mpls->ChangeNH(nh)) {
43 56 : ret = true;
44 : //Send notify of change
45 56 : mpls->get_table_partition()->Notify(mpls);
46 : }
47 2278 : }
48 2408 : return ret;
49 : }
50 :
51 : //AgentPath
52 2719 : AgentPath::AgentPath(const Peer *peer, AgentRoute *rt):
53 2719 : Path(), peer_(peer), nh_(NULL), label_(MplsTable::kInvalidLabel),
54 2719 : vxlan_id_(VxLanTable::kInvalidvxlan_id), dest_vn_list_(),
55 2719 : origin_vn_(""), sync_(false), force_policy_(false), sg_list_(),
56 2719 : tunnel_dest_(0), tunnel_bmap_(TunnelType::AllType()),
57 2719 : tunnel_type_(TunnelType::ComputeType(TunnelType::AllType())),
58 2719 : vrf_name_(""), gw_ip_(), unresolved_(true),
59 2719 : is_subnet_discard_(false), dependant_rt_(rt), path_preference_(),
60 2719 : local_ecmp_mpls_label_(rt), composite_nh_key_(NULL), subnet_service_ip_(),
61 2719 : arp_mac_(), arp_interface_(NULL), arp_valid_(false),
62 5438 : ecmp_suppressed_(false), is_local_(false), is_health_check_service_(false),
63 2719 : peer_sequence_number_(0), etree_leaf_(false), layer2_control_word_(false),
64 8157 : inactive_(false), copy_local_path_(false), parent_rt_(rt), dependent_table_(NULL) {
65 2719 : }
66 :
67 4567 : AgentPath::~AgentPath() {
68 2719 : clear_sg_list();
69 4567 : }
70 :
71 102 : uint32_t AgentPath::GetTunnelBmap() const {
72 102 : TunnelType::Type type = TunnelType::ComputeType(tunnel_bmap_);
73 102 : if ((type == (1 << TunnelType::VXLAN)) && (vxlan_id_ != 0)) {
74 0 : return (1 << TunnelType::VXLAN);
75 : } else {
76 102 : return tunnel_bmap_;
77 : }
78 : }
79 :
80 4802 : uint32_t AgentPath::GetActiveLabel() const {
81 4802 : if (tunnel_type_ == TunnelType::VXLAN) {
82 113 : return vxlan_id_;
83 : } else {
84 4689 : return label_;
85 : }
86 : }
87 :
88 39728 : NextHop* AgentPath::nexthop() const {
89 39728 : return nh_.get();
90 : }
91 :
92 51379 : const NextHop* AgentPath::ComputeNextHop(Agent *agent) const {
93 51379 : if (nh_) {
94 48375 : return nh_.get();
95 : }
96 :
97 3004 : if (unresolved_ == true) {
98 1957 : DiscardNH key;
99 1957 : return static_cast<NextHop *>
100 1957 : (agent->nexthop_table()->FindActiveEntry(&key));
101 1957 : }
102 :
103 : // Send back discard NH if dependant_rt_ is not set
104 1047 : if (dependant_rt_.get() == NULL) {
105 0 : DiscardNH key;
106 0 : return static_cast<NextHop *>
107 0 : (agent->nexthop_table()->FindActiveEntry(&key));
108 0 : }
109 :
110 : //Indirect route's path, get direct route's NH
111 1047 : const NextHop *nh = dependant_rt_.get()->GetActiveNextHop();
112 1047 : if (nh == NULL) {
113 0 : DiscardNH key;
114 0 : return static_cast<NextHop *>
115 0 : (agent->nexthop_table()->FindActiveEntry(&key));
116 0 : }
117 1047 : return nh;
118 : }
119 :
120 8395 : bool AgentPath::ChangeNH(Agent *agent, NextHop *nh) {
121 : // If NH is not found, point route to discard NH
122 8395 : bool ret = false;
123 8395 : if (nh == NULL) {
124 0 : nh = agent->nexthop_table()->discard_nh();
125 : }
126 :
127 8395 : if (nh_ != nh) {
128 2614 : nh_ = nh;
129 2614 : if (nh && nh->GetType() == NextHop::TUNNEL) {
130 69 : TunnelNH *tunnel_nh = static_cast<TunnelNH *>(nh);
131 69 : tunnel_dest_ = *tunnel_nh->GetDip();
132 : }
133 2614 : ret = true;
134 : }
135 :
136 9438 : if (peer_ && (peer_->GetType() == Peer::ECMP_PEER) &&
137 1043 : (label_ != MplsTable::kInvalidLabel)) {
138 987 : if (RebakeLabel(agent->mpls_table(), label_, nh))
139 56 : ret = true;
140 : }
141 :
142 8395 : if (PostChangeNH(agent, nh)) {
143 0 : ret = true;
144 : }
145 8395 : return ret;
146 : }
147 :
148 5704 : bool AgentPath::PostChangeNH(Agent *agent, NextHop *nh) {
149 5704 : return false;
150 : }
151 :
152 597 : bool AgentPath::RebakeAllTunnelNHinCompositeNH(const AgentRoute *sync_route) {
153 597 : if (nh_->GetType() != NextHop::COMPOSITE){
154 0 : return false;
155 : }
156 :
157 : Agent *agent =
158 597 : static_cast<AgentRouteTable *>(sync_route->get_table())->agent();
159 597 : CompositeNH *cnh = static_cast<CompositeNH *>(nh_.get());
160 :
161 : //Compute new tunnel type
162 : TunnelType::Type new_tunnel_type;
163 : //Only MPLS types are supported for multicast
164 597 : if ((sync_route->is_multicast()) && (peer_->GetType() ==
165 : Peer::MULTICAST_FABRIC_TREE_BUILDER)) {
166 0 : new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
167 0 : if (new_tunnel_type == TunnelType::VXLAN) {
168 0 : new_tunnel_type = TunnelType::MPLS_GRE;
169 : }
170 : } else {
171 597 : new_tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
172 : }
173 :
174 597 : CompositeNH *new_composite_nh = NULL;
175 597 : new_composite_nh = cnh->ChangeTunnelType(agent, new_tunnel_type);
176 597 : if (ChangeNH(agent, new_composite_nh)) {
177 : //Update composite NH key list to reflect new type
178 0 : if (composite_nh_key_)
179 0 : composite_nh_key_->ChangeTunnelType(new_tunnel_type);
180 0 : return true;
181 : }
182 597 : return false;
183 : }
184 :
185 4531 : bool AgentPath::UpdateNHPolicy(Agent *agent) {
186 4531 : bool ret = false;
187 4531 : if (nh_.get() == NULL || nh_->GetType() != NextHop::INTERFACE) {
188 1175 : return ret;
189 : }
190 :
191 3356 : const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh_.get());
192 3356 : if (intf_nh->GetInterface()->type() != Interface::VM_INTERFACE) {
193 361 : return ret;
194 : }
195 :
196 : const VmInterface *vm_port =
197 2995 : static_cast<const VmInterface *>(intf_nh->GetInterface());
198 :
199 2995 : bool policy = vm_port->policy_enabled();
200 2995 : if (force_policy_) {
201 330 : policy = true;
202 : }
203 :
204 2995 : NextHop *nh = NULL;
205 2995 : if (intf_nh->PolicyEnabled() != policy) {
206 : //Make path point to policy enabled interface
207 : InterfaceNHKey key(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
208 0 : vm_port->GetUuid(),
209 0 : vm_port->name()),
210 0 : policy, intf_nh->GetFlags(),
211 0 : intf_nh->GetDMac());
212 0 : nh = static_cast<NextHop *>
213 0 : (agent->nexthop_table()->FindActiveEntry(&key));
214 : // If NH is not found, point route to discard NH
215 0 : if (nh == NULL) {
216 0 : LOG(DEBUG, "Interface NH for <"
217 : << boost::lexical_cast<std::string>(vm_port->GetUuid())
218 : << " : policy = " << policy);
219 0 : nh = agent->nexthop_table()->discard_nh();
220 : }
221 0 : if (ChangeNH(agent, nh) == true) {
222 0 : ret = true;
223 : }
224 0 : }
225 :
226 2995 : return ret;
227 : }
228 :
229 4531 : bool AgentPath::UpdateTunnelType(Agent *agent, const AgentRoute *sync_route) {
230 : //Return if there is no change in tunnel type for non Composite NH.
231 : //For composite NH component needs to be traversed.
232 : // if tunnel type is MPLS over MPLS, transport tunnel
233 : // type might be changed ( mpls over gre or mpls over udp)
234 : // so check nh transport tunnel type and trigger update if there
235 : // is any change
236 13593 : if ((tunnel_type_ != TunnelType::MPLS_OVER_MPLS) &&
237 13571 : (tunnel_type_ == TunnelType::ComputeType(tunnel_bmap_)) &&
238 9040 : (nh_.get() && nh_.get()->GetType() != NextHop::COMPOSITE)) {
239 3915 : return false;
240 : }
241 :
242 616 : tunnel_type_ = TunnelType::ComputeType(tunnel_bmap_);
243 616 : if (tunnel_type_ == TunnelType::VXLAN &&
244 62 : vxlan_id_ == VxLanTable::kInvalidvxlan_id) {
245 0 : tunnel_type_ = TunnelType::ComputeType(TunnelType::MplsType());
246 : }
247 616 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
248 616 : const TunnelNH *tunnel_nh = static_cast<const TunnelNH*>(nh_.get());
249 616 : if (nh_.get() && nh_->GetType() == NextHop::TUNNEL) {
250 0 : if (tunnel_nh->GetTunnelType().GetType() == TunnelType::MPLS_OVER_MPLS) {
251 : const LabelledTunnelNH *label_tunnel_nh =
252 0 : static_cast<const LabelledTunnelNH*>(nh_.get());
253 : // check if transport tunnel type is changed
254 0 : if (label_tunnel_nh->GetTransportTunnelType() ==
255 0 : TunnelType::ComputeType(TunnelType::MplsType())) {
256 0 : return false;
257 : }
258 : LabelledTunnelNHKey *tnh_key =
259 0 : new LabelledTunnelNHKey(agent->fabric_vrf_name(),
260 0 : *(label_tunnel_nh->GetSip()),
261 0 : *(label_tunnel_nh->GetDip()),
262 : false, tunnel_type_,
263 0 : label_tunnel_nh->rewrite_dmac(),
264 0 : label_tunnel_nh->GetTransportLabel());
265 0 : nh_req.key.reset(tnh_key);
266 0 : nh_req.data.reset(new TunnelNHData());
267 0 : agent->nexthop_table()->Process(nh_req);
268 :
269 : LabelledTunnelNHKey nh_key(agent->fabric_vrf_name(),
270 0 : *(label_tunnel_nh->GetSip()),
271 0 : tunnel_dest_, false, tunnel_type_,
272 : label_tunnel_nh->rewrite_dmac(),
273 0 : label_tunnel_nh->GetTransportLabel());
274 0 : NextHop *nh = static_cast<NextHop *>
275 0 : (agent->nexthop_table()->FindActiveEntry(&nh_key));
276 0 : ChangeNH(agent, nh);
277 0 : } else {
278 :
279 : TunnelNHKey *tnh_key =
280 0 : new TunnelNHKey(agent->fabric_vrf_name(), *(tunnel_nh->GetSip()),
281 0 : tunnel_dest_, false, tunnel_type_);
282 0 : nh_req.key.reset(tnh_key);
283 0 : nh_req.data.reset(new TunnelNHData());
284 0 : agent->nexthop_table()->Process(nh_req);
285 :
286 0 : TunnelNHKey nh_key(agent->fabric_vrf_name(), *(tunnel_nh->GetSip()),
287 0 : tunnel_dest_, false, tunnel_type_);
288 0 : NextHop *nh = static_cast<NextHop *>
289 0 : (agent->nexthop_table()->FindActiveEntry(&nh_key));
290 0 : ChangeNH(agent, nh);
291 0 : }
292 : }
293 :
294 616 : if (nh_.get() && nh_->GetType() == NextHop::COMPOSITE) {
295 597 : RebakeAllTunnelNHinCompositeNH(sync_route);
296 : }
297 616 : return true;
298 616 : }
299 :
300 0 : void AgentPath::ImportPrevActiveNH(Agent *agent, NextHop *nh)
301 : {
302 0 : if (nh_ == nh) {
303 0 : return;
304 : }
305 : // change NH ,
306 : // assumptions here is that composite nh grid order would be different
307 : // but elements would be same , so importing previous active nh
308 : // would make sure the holes are already set in proper order
309 : // ex: previous nh order A,B, C, new path nh order would be BCA
310 : // ex2: previous nh order _,B,C, new path nh order is just B,C
311 0 : ChangeNH(agent, nh);
312 : // will there be a race condition while removing the active path,
313 : // adding new component nh?
314 : // this can be handled by calling reorder composite nh method
315 0 : if (composite_nh_key_ == NULL) {
316 0 : return;
317 : }
318 : boost::scoped_ptr<CompositeNHKey> composite_nh_key(
319 0 : composite_nh_key_->Clone());
320 0 : bool comp_nh_policy = false;
321 : //TODO: optimize here , compare compositenh_key from path and nh?
322 0 : ReorderCompositeNH(agent, composite_nh_key.get(), comp_nh_policy, NULL);
323 0 : composite_nh_key->SetPolicy(comp_nh_policy);
324 0 : ChangeCompositeNH(agent, composite_nh_key.get());
325 :
326 0 : }
327 :
328 4531 : bool AgentPath::ResolveGwNextHops(Agent *agent, const AgentRoute *sync_route) {
329 :
330 4531 : if (tunnel_type_ != TunnelType::MPLS_OVER_MPLS) {
331 4531 : return false;
332 : }
333 0 : if (ecmp_member_list_.size() == 0) {
334 0 : return false;
335 : }
336 0 : NextHop *nh = NULL;
337 0 : InetUnicastAgentRouteTable *table = NULL;
338 : table = static_cast<InetUnicastAgentRouteTable *>
339 0 : (agent->fabric_inet4_mpls_table());
340 0 : assert(table != NULL);
341 : //if ecmp member list size is one then it is non ecmp route sync
342 0 : if (ecmp_member_list_.size() == 1) {
343 0 : AgentPathEcmpComponentPtr member = ecmp_member_list_[0];
344 0 : InetUnicastRouteEntry *uc_rt = table->FindRoute(member->GetGwIpAddr());
345 : const NextHop *anh;
346 0 : if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
347 0 : set_unresolved(true);
348 0 : member->UpdateDependentRoute(NULL);
349 0 : member->SetUnresolved(true);
350 : } else {
351 0 : set_unresolved(false);
352 0 : table->RemoveUnresolvedRoute(GetParentRoute());
353 : DBEntryBase::KeyPtr key =
354 0 : anh->GetDBRequestKey();
355 : const NextHopKey *nh_key =
356 0 : static_cast<const NextHopKey*>(key.get());
357 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
358 0 : FindActiveEntry(nh_key));
359 0 : assert(nh !=NULL);
360 : //Reset to new gateway route, no nexthop for indirect route
361 0 : member->UpdateDependentRoute(uc_rt);
362 0 : member->SetUnresolved(false);
363 0 : set_nexthop(NULL);
364 0 : }
365 0 : if (nh != NULL) {
366 0 : ChangeNH(agent, nh);
367 : }
368 0 : } else {
369 : // this flag is set if atleast one member is unresolved
370 0 : bool path_unresolved = false;
371 : // if this flag is false , then
372 : // composite NH is created with one compoenent NH as discard
373 : // and avoid reording teh existing composite NH
374 : // this flag is set to true if atleast one member is resolved
375 0 : bool is_ecmp_member_resolved = false;
376 0 : ComponentNHKeyList comp_nh_list;
377 0 : bool comp_nh_policy = false;
378 : AgentPathEcmpComponentPtrList::const_iterator ecmp_member_it =
379 0 : ecmp_member_list_.begin();
380 0 : while (ecmp_member_it != ecmp_member_list_.end()) {
381 : InetUnicastRouteEntry *uc_rt =
382 0 : table->FindRoute((*ecmp_member_it)->GetGwIpAddr());
383 : const NextHop *anh;
384 0 : if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
385 0 : (*ecmp_member_it)->UpdateDependentRoute(NULL);
386 0 : (*ecmp_member_it)->SetUnresolved(true);
387 0 : if (!path_unresolved) {
388 0 : path_unresolved = true;
389 : DBEntryBase::KeyPtr key =
390 0 : agent->nexthop_table()->discard_nh()->GetDBRequestKey();
391 : NextHopKey *nh_key =
392 0 : static_cast<NextHopKey *>(key.release());
393 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
394 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(
395 0 : (*ecmp_member_it)->GetLabel(),
396 0 : std::move(nh_key_ptr)));
397 0 : comp_nh_list.push_back(component_nh_key);
398 0 : }
399 : } else {
400 0 : is_ecmp_member_resolved = true;
401 : DBEntryBase::KeyPtr key =
402 0 : anh->GetDBRequestKey();
403 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
404 0 : if (nh_key->GetType() != NextHop::COMPOSITE) {
405 : //By default all component members of composite NH
406 : //will be policy disabled, except for component NH
407 : //of type composite
408 0 : nh_key->SetPolicy(false);
409 : }
410 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
411 : ComponentNHKeyPtr component_nh_key(new
412 0 : ComponentNHKey((*ecmp_member_it)->GetLabel(),
413 0 : std::move(nh_key_ptr)));
414 0 : comp_nh_list.push_back(component_nh_key);
415 : //Reset to new gateway route, no nexthop for indirect route
416 0 : (*ecmp_member_it)->UpdateDependentRoute(uc_rt);
417 0 : (*ecmp_member_it)->SetUnresolved(false);
418 0 : }
419 0 : ecmp_member_it++;
420 : }
421 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
422 0 : nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy,
423 0 : comp_nh_list, vrf_name_));
424 0 : nh_req.data.reset(new CompositeNHData());
425 : CompositeNHKey *comp_key =
426 0 : static_cast<CompositeNHKey *>(nh_req.key.get());
427 0 : bool new_comp_nh_policy = false;
428 0 : if ((is_ecmp_member_resolved == false) ||
429 0 : ReorderCompositeNH(agent, comp_key, new_comp_nh_policy,
430 0 : sync_route->FindLocalVmPortPath())) {
431 0 : comp_key->SetPolicy(new_comp_nh_policy);
432 0 : ChangeCompositeNH(agent, comp_key);
433 : }
434 :
435 0 : set_unresolved(path_unresolved);
436 0 : }
437 :
438 :
439 0 : return true;
440 : }
441 4531 : bool AgentPath::Sync(AgentRoute *sync_route) {
442 4531 : bool ret = false;
443 4531 : bool unresolved = false;
444 :
445 : Agent *agent = static_cast<AgentRouteTable *>
446 4531 : (sync_route->get_table())->agent();
447 :
448 : // Check if there is change in policy on the interface
449 : // If yes update the path to point to policy enabled NH
450 4531 : if (UpdateNHPolicy(agent)) {
451 0 : ret = true;
452 : }
453 4531 : if (ResolveGwNextHops(agent, sync_route)) {
454 0 : return true;
455 : }
456 : //Handle tunnel type change
457 4531 : if (UpdateTunnelType(agent, sync_route)) {
458 616 : ret = true;
459 : }
460 :
461 : //Check if there was a change in local ecmp composite nexthop
462 9641 : if (nh_ && nh_->GetType() == NextHop::COMPOSITE &&
463 9645 : composite_nh_key_.get() != NULL && (copy_local_path_ ||
464 4 : local_ecmp_mpls_label_.get() != NULL)) {
465 0 : boost::scoped_ptr<CompositeNHKey> composite_nh_key(composite_nh_key_->Clone());
466 0 : bool comp_nh_policy = false;
467 0 : if (ReorderCompositeNH(agent, composite_nh_key.get(), comp_nh_policy,
468 0 : sync_route->FindLocalVmPortPath())) {
469 0 : composite_nh_key->SetPolicy(comp_nh_policy);
470 0 : if (ChangeCompositeNH(agent, composite_nh_key.get())) {
471 0 : ret = true;
472 : }
473 : }
474 0 : }
475 :
476 4531 : if (nh_ && nh_->GetType() == NextHop::ARP) {
477 2 : if (CopyArpData()) {
478 0 : ret = true;
479 : }
480 : }
481 :
482 4531 : if (vrf_name_ == Agent::NullString()) {
483 4509 : return ret;
484 : }
485 :
486 : // check dependant route change
487 : // this is needed only for inet routes
488 22 : InetUnicastAgentRouteTable *table = NULL;
489 22 : table = dynamic_cast<InetUnicastAgentRouteTable *>
490 22 : (sync_route->get_table());
491 22 : if (table == NULL) {
492 0 : return ret;
493 : }
494 :
495 22 : InetUnicastRouteEntry *rt = NULL;
496 :
497 22 : rt = table->FindRoute(gw_ip_);
498 22 : if (rt == sync_route) {
499 4 : rt = NULL;
500 : }
501 : const NextHop *anh;
502 22 : if (rt == NULL || rt->prefix_length() == 0) {
503 8 : if (agent->params()->subnet_hosts_resolvable() == false &&
504 0 : agent->fabric_vrf_name() == vrf_name_) {
505 0 : unresolved = false;
506 0 : assert(gw_ip_.is_v4());
507 0 : table->AddArpReq(vrf_name_, gw_ip_.to_v4(), vrf_name_,
508 : agent->vhost_interface(), false,
509 0 : dest_vn_list_, sg_list_, tag_list_);
510 : } else {
511 8 : unresolved = true;
512 : }
513 14 : } else if ((anh = rt->GetActiveNextHop()) == NULL) {
514 0 : if (agent->params()->subnet_hosts_resolvable() == false &&
515 0 : agent->fabric_vrf_name() == vrf_name_) {
516 0 : unresolved = false;
517 0 : assert(gw_ip_.is_v4());
518 0 : table->AddArpReq(vrf_name_, gw_ip_.to_v4(), vrf_name_,
519 : agent->vhost_interface(), false,
520 0 : dest_vn_list_, sg_list_, tag_list_);
521 : } else {
522 0 : unresolved = true;
523 : }
524 14 : } else if (anh->GetType() == NextHop::RESOLVE) {
525 4 : const ResolveNH *nh =
526 : static_cast<const ResolveNH *>(anh);
527 4 : std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
528 4 : if (nh->get_interface()->vrf()->forwarding_vrf()) {
529 4 : nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
530 : }
531 :
532 4 : assert(gw_ip_.is_v4());
533 4 : table->AddArpReq(vrf_name_, gw_ip_.to_v4(), nexthop_vrf,
534 4 : nh->get_interface(), nh->PolicyEnabled(), dest_vn_list_,
535 4 : sg_list_, tag_list_);
536 4 : unresolved = true;
537 4 : } else {
538 10 : unresolved = false;
539 : }
540 :
541 22 : if (unresolved_ != unresolved) {
542 4 : unresolved_ = unresolved;
543 4 : ret = true;
544 : }
545 :
546 : // Reset to new gateway route, no nexthop for indirect route
547 22 : if (dependant_rt_.get() != rt) {
548 8 : dependant_rt_.reset(rt);
549 8 : ret = true;
550 8 : if (rt) {
551 : TunnelType::TypeBmap dep_bmap =
552 5 : dependant_rt_->GetActivePath()->tunnel_bmap();
553 5 : if (tunnel_bmap_ & 1 << TunnelType::NATIVE) {
554 4 : dep_bmap |= (1 << TunnelType::NATIVE);
555 : }
556 5 : set_tunnel_bmap(dep_bmap);
557 : }
558 : }
559 22 : return ret;
560 : }
561 :
562 10386 : bool AgentPath::IsLess(const AgentPath &r_path) const {
563 10386 : if (peer()->GetType() == r_path.peer()->GetType()) {
564 3556 : if (path_preference() != r_path.path_preference()) {
565 : //If right path has lesser preference, then
566 : //it should be after the current entry
567 : //Hence the reverse check
568 388 : return (r_path.path_preference() < path_preference());
569 : }
570 : }
571 :
572 9998 : return peer()->IsLess(r_path.peer());
573 : }
574 :
575 115178 : const AgentPath *AgentPath::UsablePath() const {
576 115178 : return this;
577 : }
578 :
579 420 : void AgentPath::set_nexthop(NextHop *nh) {
580 420 : nh_ = nh;
581 420 : }
582 :
583 10 : bool AgentPath::CopyArpData() {
584 10 : bool ret = false;
585 10 : if (nh_ && nh_->GetType() == NextHop::ARP) {
586 10 : const ArpNH *arp_nh = static_cast<const ArpNH *>(nh_.get());
587 10 : if (arp_mac() != arp_nh->GetMac()) {
588 0 : set_arp_mac(arp_nh->GetMac());
589 0 : ret = true;
590 : }
591 :
592 10 : if (arp_interface() != arp_nh->GetInterface()) {
593 4 : set_arp_interface(arp_nh->GetInterface());
594 4 : ret = true;
595 : }
596 :
597 10 : if (arp_valid() != arp_nh->IsValid()) {
598 0 : set_arp_valid(arp_nh->IsValid());
599 0 : ret = true;
600 : }
601 : }
602 10 : return ret;
603 : }
604 :
605 0 : bool AgentPath::CopyNdpData() {
606 0 : bool ret = false;
607 0 : if (nh_ && nh_->GetType() == NextHop::NDP) {
608 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(nh_.get());
609 0 : if (arp_mac() != ndp_nh->GetMac()) {
610 0 : set_arp_mac(ndp_nh->GetMac());
611 0 : ret = true;
612 : }
613 :
614 0 : if (arp_interface() != ndp_nh->GetInterface()) {
615 0 : set_arp_interface(ndp_nh->GetInterface());
616 0 : ret = true;
617 : }
618 :
619 0 : if (arp_valid() != ndp_nh->IsValid()) {
620 0 : set_arp_valid(ndp_nh->IsValid());
621 0 : ret = true;
622 : }
623 : }
624 0 : return ret;
625 : }
626 :
627 338 : EvpnDerivedPath::EvpnDerivedPath(const EvpnPeer *evpn_peer,
628 : const IpAddress &ip_addr,
629 : uint32_t ethernet_tag,
630 338 : const std::string &parent) :
631 : AgentPath(evpn_peer, NULL),
632 676 : ip_addr_(ip_addr), ethernet_tag_(ethernet_tag),
633 338 : parent_(parent){
634 338 : }
635 :
636 2674 : bool EvpnDerivedPath::IsLess(const AgentPath &r_path) const {
637 2674 : const EvpnDerivedPath *r_evpn_path =
638 2674 : dynamic_cast<const EvpnDerivedPath *>(&r_path);
639 2674 : if (r_evpn_path != NULL) {
640 2361 : if (r_evpn_path->ip_addr() != ip_addr_) {
641 2361 : return (ip_addr_ < r_evpn_path->ip_addr());
642 : }
643 : }
644 :
645 313 : return peer()->IsLess(r_path.peer());
646 : }
647 :
648 7743 : const NextHop *EvpnDerivedPath::ComputeNextHop(Agent *agent) const {
649 7743 : return nexthop();
650 : }
651 :
652 1847 : EvpnDerivedPathData::EvpnDerivedPathData(const EvpnRouteEntry *evpn_rt) :
653 : AgentRouteData(AgentRouteData::ADD_DEL_CHANGE,
654 1847 : evpn_rt->is_multicast(), 0),
655 1847 : ethernet_tag_(evpn_rt->ethernet_tag()), ip_addr_(evpn_rt->prefix_address()),
656 3694 : reference_path_(evpn_rt->GetActivePath()), ecmp_suppressed_(false) {
657 : // For debuging add peer of active path in parent as well
658 1847 : std::stringstream s;
659 1847 : s << evpn_rt->ToString();
660 1847 : s << " ";
661 1847 : if (reference_path_ && reference_path_->peer())
662 1509 : s << reference_path_->peer()->GetName();
663 1847 : parent_ = s.str();
664 1847 : }
665 :
666 338 : AgentPath *EvpnDerivedPathData::CreateAgentPath(const Peer *peer,
667 : AgentRoute *rt) const {
668 338 : const EvpnPeer *evpn_peer = dynamic_cast<const EvpnPeer *>(peer);
669 338 : assert(evpn_peer != NULL);
670 338 : return (new EvpnDerivedPath(evpn_peer, ip_addr_, ethernet_tag_,
671 338 : parent_));
672 : }
673 :
674 1509 : bool EvpnDerivedPathData::AddChangePathExtended(Agent *agent, AgentPath *path,
675 : const AgentRoute *rt) {
676 1509 : bool ret = false;
677 1509 : EvpnDerivedPath *evpn_path = dynamic_cast<EvpnDerivedPath *>(path);
678 1509 : assert(evpn_path != NULL);
679 :
680 1509 : evpn_path->set_tunnel_dest(reference_path_->tunnel_dest());
681 1509 : uint32_t label = reference_path_->label();
682 1509 : if (evpn_path->label() != label) {
683 454 : evpn_path->set_label(label);
684 454 : ret = true;
685 : }
686 :
687 1509 : uint32_t vxlan_id = reference_path_->vxlan_id();
688 1509 : if (evpn_path->vxlan_id() != vxlan_id) {
689 246 : evpn_path->set_vxlan_id(vxlan_id);
690 246 : ret = true;
691 : }
692 :
693 1509 : uint32_t tunnel_bmap = reference_path_->tunnel_bmap();
694 1509 : if (evpn_path->tunnel_bmap() != tunnel_bmap) {
695 7 : evpn_path->set_tunnel_bmap(tunnel_bmap);
696 7 : ret = true;
697 : }
698 :
699 1509 : TunnelType::Type tunnel_type = reference_path_->tunnel_type();
700 1509 : if (evpn_path->tunnel_type() != tunnel_type) {
701 7 : evpn_path->set_tunnel_type(tunnel_type);
702 7 : ret = true;
703 : }
704 :
705 1509 : PathPreference pref = reference_path_->path_preference();
706 1509 : if (evpn_path->path_preference() != pref) {
707 : // Take path preference from parent path
708 105 : evpn_path->set_path_preference(pref);
709 105 : ret = true;
710 : }
711 :
712 3018 : if (evpn_path->nexthop() !=
713 1509 : reference_path_->nexthop()) {
714 416 : evpn_path->set_nexthop(reference_path_->nexthop());
715 416 : ret = true;
716 : }
717 :
718 1509 : const SecurityGroupList &sg_list = reference_path_->sg_list();
719 1509 : if (evpn_path->sg_list() != sg_list) {
720 18 : evpn_path->set_sg_list(sg_list);
721 18 : ret = true;
722 : }
723 :
724 1509 : const TagList &tag_list = reference_path_->tag_list();
725 1509 : if (evpn_path->tag_list() != tag_list) {
726 0 : evpn_path->set_tag_list(tag_list);
727 0 : ret = true;
728 : }
729 :
730 1509 : const VnListType &dest_vn_list = reference_path_->dest_vn_list();
731 1509 : if (evpn_path->dest_vn_list() != dest_vn_list) {
732 338 : evpn_path->set_dest_vn_list(dest_vn_list);
733 338 : ret = true;
734 : }
735 :
736 1509 : if (evpn_path->ecmp_suppressed() != ecmp_suppressed_) {
737 0 : evpn_path->set_ecmp_suppressed(ecmp_suppressed_);
738 0 : ret = true;
739 : }
740 :
741 1509 : if (evpn_path->etree_leaf() != reference_path_->etree_leaf()) {
742 0 : evpn_path->set_etree_leaf(reference_path_->etree_leaf());
743 0 : ret = true;
744 : }
745 :
746 1509 : if (evpn_path->ResyncControlWord(rt)) {
747 0 : ret = true;
748 : }
749 :
750 1509 : path->set_unresolved(false);
751 :
752 1509 : return ret;
753 1509 : }
754 :
755 648 : bool EvpnDerivedPathData::CanDeletePath(Agent *agent, AgentPath *path,
756 : const AgentRoute *rt) const {
757 : const EvpnDerivedPath *evpn_path =
758 648 : dynamic_cast<const EvpnDerivedPath *>(path);
759 648 : assert(evpn_path != NULL);
760 :
761 648 : if (evpn_path->ethernet_tag() != ethernet_tag())
762 0 : return false;
763 :
764 648 : return (evpn_path->ip_addr() == ip_addr());
765 : }
766 :
767 498 : bool HostRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
768 : const AgentRoute *rt) {
769 498 : bool ret = false;
770 498 : NextHop *nh = NULL;
771 :
772 498 : InterfaceNHKey key(intf_.Clone(), policy_, InterfaceNHFlags::INET4,
773 498 : agent->pkt_interface_mac());
774 498 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
775 498 : VnListType dest_vn_list;
776 498 : dest_vn_list.insert(dest_vn_name_);
777 498 : if (path->dest_vn_list() != dest_vn_list) {
778 418 : path->set_dest_vn_list(dest_vn_list);
779 418 : ret = true;
780 : }
781 :
782 498 : path->set_unresolved(false);
783 498 : if (path->ChangeNH(agent, nh) == true)
784 418 : ret = true;
785 :
786 498 : return ret;
787 498 : }
788 :
789 498 : bool HostRoute::UpdateRoute(AgentRoute *rt) {
790 498 : InetUnicastRouteEntry *uc_rt =
791 : static_cast<InetUnicastRouteEntry *>(rt);
792 498 : AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
793 836 : if ((table->GetTableType() != Agent::INET4_UNICAST) &&
794 338 : (table->GetTableType() != Agent::INET6_UNICAST))
795 140 : return false;
796 :
797 358 : return uc_rt->UpdateRouteFlags(false, false, true);
798 : }
799 :
800 344 : bool L2ReceiveRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
801 : const AgentRoute *rt) {
802 344 : bool ret = false;
803 :
804 344 : path->set_unresolved(false);
805 :
806 344 : VnListType dest_vn_list;
807 344 : dest_vn_list.insert(dest_vn_name_);
808 344 : if (path->dest_vn_list() != dest_vn_list) {
809 261 : path->set_dest_vn_list(dest_vn_list);
810 261 : ret = true;
811 : }
812 :
813 344 : if (path->label() != mpls_label_) {
814 261 : path->set_label(mpls_label_);
815 261 : ret = true;
816 : }
817 :
818 344 : if (path->vxlan_id() != vxlan_id_) {
819 0 : path->set_vxlan_id(vxlan_id_);
820 0 : ret = true;
821 : }
822 :
823 344 : if (path->path_preference().ConfigChanged(path_preference_)) {
824 113 : path->set_path_preference(path_preference_);
825 113 : ret = true;
826 : }
827 :
828 344 : if (path->peer() && path->peer()->GetType() == Peer::BGP_PEER) {
829 : //Copy entire path preference for BGP peer path,
830 : //since allowed-address pair config doesn't modify
831 : //preference on BGP path
832 0 : if (path->path_preference() != path_preference_) {
833 0 : path->set_path_preference(path_preference_);
834 0 : ret = true;
835 : }
836 : }
837 :
838 344 : if (path->ChangeNH(agent, agent->nexthop_table()->l2_receive_nh()) == true)
839 261 : ret = true;
840 :
841 344 : return ret;
842 344 : }
843 :
844 0 : bool InetInterfaceRoute::UpdateRoute(AgentRoute *rt) {
845 0 : AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
846 0 : if ((table->GetTableType() != Agent::INET4_UNICAST) &&
847 0 : (table->GetTableType() != Agent::INET6_UNICAST))
848 0 : return false;
849 :
850 0 : InetUnicastRouteEntry *uc_rt = static_cast<InetUnicastRouteEntry *>(rt);
851 :
852 0 : return uc_rt->UpdateRouteFlags(false, false, true);
853 : }
854 :
855 0 : bool InetInterfaceRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
856 : const AgentRoute *rt) {
857 0 : bool ret = false;
858 0 : NextHop *nh = NULL;
859 : InterfaceNHKey key(intf_.Clone(), false, InterfaceNHFlags::INET4,
860 0 : agent->pkt_interface_mac());
861 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
862 0 : if (path->dest_vn_list() != dest_vn_list_) {
863 0 : path->set_dest_vn_list(dest_vn_list_);
864 0 : ret = true;
865 : }
866 :
867 0 : if (path->label() != label_) {
868 0 : path->set_label(label_);
869 0 : ret = true;
870 : }
871 :
872 0 : path->set_tunnel_bmap(tunnel_bmap_);
873 0 : TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
874 0 : if (tunnel_type != path->tunnel_type()) {
875 0 : path->set_tunnel_type(tunnel_type);
876 0 : ret = true;
877 : }
878 :
879 0 : path->set_unresolved(false);
880 0 : if (path->ChangeNH(agent, nh) == true)
881 0 : ret = true;
882 :
883 0 : return ret;
884 0 : }
885 :
886 0 : bool DropRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
887 : const AgentRoute *rt) {
888 0 : bool ret = false;
889 :
890 0 : VnListType dest_vn_list;
891 0 : dest_vn_list.insert(vn_);
892 0 : if (path->dest_vn_list() != dest_vn_list) {
893 0 : path->set_dest_vn_list(dest_vn_list);
894 0 : ret = true;
895 : }
896 :
897 0 : NextHop *nh = agent->nexthop_table()->discard_nh();
898 0 : path->set_unresolved(false);
899 0 : if (path->ChangeNH(agent, nh) == true) {
900 0 : ret = true;
901 : }
902 :
903 0 : return ret;
904 0 : }
905 :
906 2630 : bool LocalVmRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
907 : const AgentRoute *rt) {
908 2630 : bool ret = false;
909 2630 : NextHop *nh = NULL;
910 2630 : SecurityGroupList path_sg_list;
911 2630 : TagList path_tag_list;
912 2630 : CommunityList path_communities;
913 :
914 : //TODO Based on key table type pick up interface
915 2630 : VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_.uuid_, intf_.name_);
916 2630 : VmInterface *vm_port = static_cast<VmInterface *>
917 2630 : (agent->interface_table()->FindActiveEntry(&intf_key));
918 :
919 2630 : bool policy = false;
920 2630 : if (vm_port) {
921 : // Use policy based NH if policy enabled on interface
922 2630 : if (vm_port->policy_enabled()) {
923 2626 : policy = true;
924 2626 : ret = true;
925 : }
926 : }
927 :
928 2630 : if (native_encap_) {
929 2 : tunnel_bmap_ |= (1 << TunnelType::NATIVE);
930 : }
931 :
932 2630 : if (tunnel_bmap_ != path->tunnel_bmap()) {
933 609 : path->set_tunnel_bmap(tunnel_bmap_);
934 609 : ret = true;
935 : }
936 :
937 2630 : TunnelType::Type new_tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
938 2630 : if (new_tunnel_type == TunnelType::VXLAN &&
939 0 : vxlan_id_ == VxLanTable::kInvalidvxlan_id) {
940 0 : new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
941 : }
942 :
943 2630 : if (path->tunnel_type() != new_tunnel_type) {
944 0 : path->set_tunnel_type(new_tunnel_type);
945 0 : ret = true;
946 : }
947 :
948 : // If policy force-enabled in request, enable policy
949 2630 : path->set_force_policy(force_policy_);
950 2630 : if (force_policy_) {
951 330 : policy = true;
952 : }
953 :
954 2630 : MacAddress mac = MacAddress::ZeroMac();
955 2630 : if (vm_port) {
956 2630 : mac = vm_port->vm_mac();
957 : const InetUnicastRouteEntry *ip_rt =
958 2630 : dynamic_cast<const InetUnicastRouteEntry *>(rt);
959 2630 : if (ip_rt) {
960 1082 : mac = vm_port->GetIpMac(ip_rt->prefix_address(), ip_rt->prefix_length());
961 : }
962 : const EvpnRouteEntry *evpn_rt =
963 2630 : dynamic_cast<const EvpnRouteEntry *>(rt);
964 2630 : if (evpn_rt && vm_port->mac_ip_learning_enable()) {
965 0 : mac = evpn_rt->mac();
966 : }
967 : }
968 2630 : if (vm_port && vm_port->mac_ip_learning_enable()) {
969 0 : MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(mpls_label_);
970 0 : if (mpls != NULL) {
971 0 : const InterfaceNH *label_nh = dynamic_cast<const InterfaceNH *>(mpls->nexthop());
972 0 : if (label_nh) {
973 0 : const MacAddress nh_dmac = label_nh->GetDMac();
974 0 : if (mac == vm_port->vm_mac() && nh_dmac != vm_port->vm_mac()) {
975 0 : mac = nh_dmac;
976 : }
977 : }
978 : }
979 : }
980 2630 : InterfaceNHKey key(intf_.Clone(), policy, flags_, mac);
981 2630 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
982 :
983 2630 : if (path->label() != mpls_label_) {
984 939 : path->set_label(mpls_label_);
985 939 : ret = true;
986 : }
987 :
988 2630 : if (path->vxlan_id() != vxlan_id_) {
989 312 : path->set_vxlan_id(vxlan_id_);
990 312 : ret = true;
991 : }
992 :
993 2630 : if (path->dest_vn_list() != dest_vn_list_) {
994 939 : path->set_dest_vn_list(dest_vn_list_);
995 939 : ret = true;
996 : }
997 :
998 2630 : path_sg_list = path->sg_list();
999 2630 : if (path_sg_list != sg_list_) {
1000 15 : path->set_sg_list(sg_list_);
1001 15 : ret = true;
1002 : }
1003 :
1004 2630 : path_tag_list = path->tag_list();
1005 2630 : if (path_tag_list != tag_list_) {
1006 0 : path->set_tag_list(tag_list_);
1007 0 : ret = true;
1008 : }
1009 :
1010 2630 : path_communities = path->communities();
1011 2630 : if (path_communities != communities_) {
1012 0 : path->set_communities(communities_);
1013 0 : ret = true;
1014 : }
1015 :
1016 : //Priority and sequence no of path are updated from path
1017 : //preference state machine
1018 : //Path preference value enqueued here would be copied
1019 : //only if
1020 : //1> ecmp field is set to true, meaning path would be
1021 : // active-active
1022 : //2> static preference is set, meaning external entity
1023 : // would specify the preference of this path(ex LBaaS)
1024 : //3> Change in priority when static preference is set
1025 4994 : if (path->path_preference().ConfigChanged(path_preference_) ||
1026 2364 : path->peer() == agent->fabric_rt_export_peer()) {
1027 266 : path->set_path_preference(path_preference_);
1028 266 : ret = true;
1029 : }
1030 :
1031 2630 : if (path->peer() && path->peer()->GetType() == Peer::BGP_PEER) {
1032 : //Copy entire path preference for BGP peer path,
1033 : //since allowed-address pair config doesn't modify
1034 : //preference on BGP path
1035 0 : if (path->path_preference() != path_preference_) {
1036 0 : path->set_path_preference(path_preference_);
1037 0 : ret = true;
1038 : }
1039 : }
1040 :
1041 : // When BGP path was added, the policy flag in BGP path was based on
1042 : // interface config at that instance. If the policy flag changes in
1043 : // path for "Local Peer", we should change policy flag on BGP peer
1044 : // also. Check if policy has changed and enable SYNC of all path in
1045 : // this case
1046 : // Ideally his is needed only for LocalPath. But, having code for all
1047 : // paths does not have any problem
1048 2630 : bool old_policy = false;
1049 2630 : bool new_policy = false;
1050 2630 : if (path->ComputeNextHop(agent) && path->ComputeNextHop(agent)->PolicyEnabled())
1051 1691 : old_policy = true;
1052 2630 : if (nh && nh->PolicyEnabled())
1053 2626 : new_policy = true;
1054 2630 : if (old_policy != new_policy) {
1055 935 : sync_route_ = true;
1056 : }
1057 :
1058 2630 : if (path->subnet_service_ip() != subnet_service_ip_) {
1059 329 : path->set_subnet_service_ip(subnet_service_ip_);
1060 329 : ret = true;
1061 : }
1062 :
1063 2630 : path->set_unresolved(false);
1064 2630 : path->SyncRoute(sync_route_);
1065 :
1066 2630 : if (ecmp_load_balance_ != path->ecmp_load_balance()) {
1067 0 : path->set_ecmp_load_balance(ecmp_load_balance_);
1068 0 : ret = true;
1069 : }
1070 :
1071 2630 : if (path->ChangeNH(agent, nh) == true)
1072 939 : ret = true;
1073 :
1074 2630 : if (is_local_ != path->is_local()) {
1075 0 : path->set_is_local(is_local_);
1076 0 : ret = true;
1077 : }
1078 :
1079 2630 : if (is_health_check_service_ != path->is_health_check_service()) {
1080 0 : path->set_is_health_check_service(is_health_check_service_);
1081 0 : ret = true;
1082 : }
1083 :
1084 2630 : if (etree_leaf_ != path->etree_leaf()) {
1085 0 : path->set_etree_leaf(etree_leaf_);
1086 0 : ret = true;
1087 : }
1088 :
1089 2630 : if (native_vrf_id_ != path->native_vrf_id()) {
1090 365 : path->set_native_vrf_id(native_vrf_id_);
1091 365 : ret = true;
1092 : }
1093 2630 : path->SetDynamicLearntRouteFlag(is_learnt_route_);
1094 :
1095 2630 : return ret;
1096 2630 : }
1097 :
1098 2630 : bool LocalVmRoute::UpdateRoute(AgentRoute *rt) {
1099 2630 : AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
1100 4343 : if ((table->GetTableType() != Agent::INET4_UNICAST) &&
1101 1713 : (table->GetTableType() != Agent::INET6_UNICAST)) {
1102 1548 : return false;
1103 : }
1104 :
1105 : /* Route Reflect will not have the field populated and we do not
1106 : * want to override the route type for reflected routes */
1107 1082 : if (intf_route_type().empty()) {
1108 330 : return false;
1109 : }
1110 :
1111 752 : if (intf_route_type().compare(rt->intf_route_type()) != 0) {
1112 0 : rt->set_intf_route_type(intf_route_type());
1113 0 : return true;
1114 : }
1115 :
1116 752 : return false;
1117 : }
1118 :
1119 :
1120 0 : bool PBBRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
1121 : const AgentRoute *rt) {
1122 0 : bool ret = false;
1123 0 : NextHop *nh = NULL;
1124 0 : SecurityGroupList path_sg_list;
1125 0 : TagList path_tag_list;
1126 0 : CommunityList path_communities;
1127 :
1128 0 : VrfEntry *vrf = static_cast<VrfEntry *>
1129 0 : (agent->vrf_table()->FindActiveEntry(&vrf_key_));
1130 :
1131 0 : if (vrf != NULL) {
1132 : //Create PBB NH
1133 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1134 0 : nh_req.key.reset(new PBBNHKey(vrf_key_.name_, dmac_, isid_));
1135 0 : nh_req.data.reset(new PBBNHData());
1136 0 : agent->nexthop_table()->Process(nh_req);
1137 :
1138 0 : PBBNHKey pbb_nh_key(vrf_key_.name_, dmac_, isid_);
1139 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
1140 0 : FindActiveEntry(&pbb_nh_key));
1141 0 : }
1142 :
1143 0 : if (path->dest_vn_list() != dest_vn_list_) {
1144 0 : path->set_dest_vn_list(dest_vn_list_);
1145 0 : ret = true;
1146 : }
1147 :
1148 0 : path_sg_list = path->sg_list();
1149 0 : if (path_sg_list != sg_list_) {
1150 0 : path->set_sg_list(sg_list_);
1151 0 : ret = true;
1152 : }
1153 :
1154 0 : path_tag_list = path->tag_list();
1155 0 : if (path_tag_list != tag_list_) {
1156 0 : path->set_tag_list(tag_list_);
1157 0 : ret = true;
1158 : }
1159 :
1160 : //Copy over entire path preference structure, whenever there is a
1161 :
1162 0 : if (path->ChangeNH(agent, nh) == true) {
1163 0 : ret = true;
1164 : }
1165 :
1166 0 : path->set_unresolved(false);
1167 0 : return ret;
1168 0 : }
1169 :
1170 0 : bool VlanNhRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
1171 : const AgentRoute *rt) {
1172 0 : bool ret = false;
1173 0 : NextHop *nh = NULL;
1174 0 : SecurityGroupList path_sg_list;
1175 0 : TagList path_tag_list;
1176 :
1177 0 : assert(intf_.type_ == Interface::VM_INTERFACE);
1178 0 : VlanNHKey key(intf_.uuid_, tag_);
1179 :
1180 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
1181 0 : if (nh) {
1182 0 : assert(nh->GetType() == NextHop::VLAN);
1183 : }
1184 :
1185 0 : if (path->label() != label_) {
1186 0 : path->set_label(label_);
1187 0 : ret = true;
1188 : }
1189 :
1190 0 : if (path->dest_vn_list() != dest_vn_list_) {
1191 0 : path->set_dest_vn_list(dest_vn_list_);
1192 0 : ret = true;
1193 : }
1194 :
1195 0 : path_sg_list = path->sg_list();
1196 0 : if (path_sg_list != sg_list_) {
1197 0 : path->set_sg_list(sg_list_);
1198 0 : ret = true;
1199 : }
1200 :
1201 0 : path_tag_list = path->tag_list();
1202 0 : if (path_tag_list != tag_list_) {
1203 0 : path->set_tag_list(tag_list_);
1204 0 : ret = true;
1205 : }
1206 :
1207 : //Copy over entire path preference structure, whenever there is a
1208 :
1209 : //Copy over entire path preference structure, whenever there is a
1210 : //transition from active-active to active-backup struture
1211 0 : if (path->path_preference().ConfigChanged(path_preference_)) {
1212 0 : path->set_path_preference(path_preference_);
1213 0 : ret = true;
1214 : }
1215 :
1216 0 : path->set_tunnel_bmap(tunnel_bmap_);
1217 0 : TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
1218 0 : if (tunnel_type != path->tunnel_type()) {
1219 0 : path->set_tunnel_type(tunnel_type);
1220 0 : ret = true;
1221 : }
1222 :
1223 0 : path->set_unresolved(false);
1224 0 : if (path->ChangeNH(agent, nh) == true) {
1225 0 : ret = true;
1226 : }
1227 :
1228 0 : return ret;
1229 0 : }
1230 :
1231 2 : bool ResolveRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
1232 : const AgentRoute *rt) {
1233 2 : bool ret = false;
1234 2 : NextHop *nh = NULL;
1235 2 : ResolveNHKey key(intf_key_.get(), policy_);
1236 :
1237 2 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
1238 2 : path->set_unresolved(false);
1239 :
1240 2 : VnListType dest_vn_list;
1241 2 : dest_vn_list.insert(dest_vn_name_);
1242 2 : if (path->dest_vn_list() != dest_vn_list) {
1243 2 : path->set_dest_vn_list(dest_vn_list);
1244 2 : ret = true;
1245 : }
1246 :
1247 2 : if (path->label() != label_) {
1248 0 : path->set_label(label_);
1249 0 : ret = true;
1250 : }
1251 :
1252 2 : if (path->sg_list() != path_sg_list_) {
1253 0 : path->set_sg_list(path_sg_list_);
1254 0 : ret = true;
1255 : }
1256 :
1257 : //By default resolve route on gateway interface
1258 : //is supported with MPLSoGRE or MplsoUdp port
1259 2 : path->set_tunnel_bmap(TunnelType::MplsType());
1260 : TunnelType::Type new_tunnel_type =
1261 2 : TunnelType::ComputeType(TunnelType::MplsType());
1262 2 : if (path->tunnel_type() != new_tunnel_type) {
1263 0 : path->set_tunnel_type(new_tunnel_type);
1264 : }
1265 :
1266 2 : if (path->ChangeNH(agent, nh) == true)
1267 2 : ret = true;
1268 :
1269 2 : return ret;
1270 2 : }
1271 :
1272 18 : bool ReceiveRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
1273 : const AgentRoute *rt) {
1274 18 : bool ret = false;
1275 18 : NextHop *nh = NULL;
1276 :
1277 : //TODO check if it needs to know table type
1278 18 : ReceiveNHKey key(intf_->Clone(), policy_);
1279 18 : nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
1280 18 : path->set_unresolved(false);
1281 :
1282 18 : VnListType dest_vn_list;
1283 18 : dest_vn_list.insert(vn_);
1284 18 : if (path->dest_vn_list() != dest_vn_list) {
1285 10 : path->set_dest_vn_list(dest_vn_list);
1286 10 : ret = true;
1287 : }
1288 :
1289 18 : if (path->label() != label_) {
1290 10 : path->set_label(label_);
1291 10 : ret = true;
1292 : }
1293 :
1294 18 : path->set_tunnel_bmap(tunnel_bmap_);
1295 :
1296 18 : if (path->ChangeNH(agent, nh) == true)
1297 10 : ret = true;
1298 :
1299 18 : return ret;
1300 18 : }
1301 :
1302 18 : bool ReceiveRoute::UpdateRoute(AgentRoute *rt) {
1303 18 : AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
1304 22 : if ((table->GetTableType() != Agent::INET4_UNICAST) &&
1305 4 : (table->GetTableType() != Agent::INET6_UNICAST))
1306 2 : return false;
1307 :
1308 16 : InetUnicastRouteEntry *uc_rt =
1309 : static_cast<InetUnicastRouteEntry *>(rt);
1310 :
1311 : // Receive route can be a /32 route of multicast-subnet route
1312 : // proxy_arp_ is set only for host route. So, set ipam_host_route_ if
1313 : // proxy_arp_ enabled
1314 16 : return uc_rt->UpdateRouteFlags(false, ipam_host_route_, proxy_arp_);
1315 : }
1316 :
1317 196 : MulticastRoutePath::MulticastRoutePath(const Peer *peer) :
1318 196 : AgentPath(peer, NULL), original_nh_(),
1319 196 : evpn_label_(MplsTable::kInvalidLabel),
1320 196 : fabric_label_(MplsTable::kInvalidLabel) {
1321 196 : }
1322 :
1323 2691 : bool MulticastRoutePath::PostChangeNH(Agent *agent, NextHop *nh) {
1324 2691 : bool ret = false;
1325 2691 : if (!peer())
1326 0 : return false;
1327 :
1328 2691 : if (peer()->GetType() != Peer::MULTICAST_PEER)
1329 1400 : return false;
1330 :
1331 : //Bake for label in path
1332 1291 : if (RebakeLabel(agent->mpls_table(), label(), nh))
1333 0 : ret = true;
1334 :
1335 : //If path label is not same as evpn label, then rebake evpn label
1336 1356 : if ((label() != evpn_label_) &&
1337 65 : RebakeLabel(agent->mpls_table(), evpn_label_, nh))
1338 0 : ret = true;
1339 :
1340 : //If path label is not same as fmg label, then rebake fmg label
1341 1356 : if ((label() != fabric_label_) &&
1342 65 : RebakeLabel(agent->mpls_table(), fabric_label_, nh))
1343 0 : ret = true;
1344 :
1345 1291 : return ret;
1346 : }
1347 :
1348 0 : NextHop *MulticastRoutePath::UpdateNH(Agent *agent,
1349 : CompositeNH *cnh,
1350 : const TsnElector *te) {
1351 0 : ComponentNHKeyList new_component_nh_key_list;
1352 0 : for (ComponentNHKeyList::const_iterator it =
1353 0 : cnh->component_nh_key_list().begin();
1354 0 : it != cnh->component_nh_key_list().end(); it++) {
1355 0 : if ((*it) == NULL)
1356 0 : continue;
1357 : const TunnelNHKey *tunnel_nh_key =
1358 0 : static_cast<const TunnelNHKey *>((*it)->nh_key());
1359 0 : if (std::find(te->ManagedPhysicalDevices().begin(),
1360 0 : te->ManagedPhysicalDevices().end(),
1361 0 : tunnel_nh_key->dip().to_string()) !=
1362 0 : te->ManagedPhysicalDevices().end()) {
1363 0 : new_component_nh_key_list.push_back(*it);
1364 : }
1365 : }
1366 0 : set_original_nh(cnh);
1367 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1368 0 : nh_req.key.reset(new CompositeNHKey(Composite::EVPN, false,
1369 : new_component_nh_key_list,
1370 0 : cnh->vrf()->GetName()));
1371 0 : nh_req.data.reset(new CompositeNHData(cnh->pbb_nh(),
1372 0 : cnh->learning_enabled(), false));
1373 0 : agent->nexthop_table()->Process(nh_req);
1374 0 : NextHop *new_nh = static_cast<NextHop *>(agent->nexthop_table()->
1375 0 : FindActiveEntry(nh_req.key.get()));
1376 0 : assert(new_nh);
1377 0 : return new_nh;
1378 0 : }
1379 :
1380 131 : AgentPath *MulticastRoute::CreateAgentPath(const Peer *peer,
1381 : AgentRoute *rt) const {
1382 131 : return (new MulticastRoutePath(peer));
1383 : }
1384 :
1385 1301 : bool MulticastRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
1386 : const AgentRoute *rt) {
1387 1301 : bool ret = false;
1388 1301 : NextHop *nh = NULL;
1389 :
1390 1301 : agent->nexthop_table()->Process(composite_nh_req_);
1391 2602 : nh = static_cast<NextHop *>(agent->nexthop_table()->
1392 1301 : FindActiveEntry(composite_nh_req_.key.get()));
1393 1301 : assert(nh);
1394 :
1395 1301 : if (agent->params()->agent_mode() == AgentParam::TSN_NO_FORWARDING_AGENT) {
1396 : MulticastRoutePath *multicast_path =
1397 0 : dynamic_cast<MulticastRoutePath *>(path);
1398 0 : multicast_path->set_original_nh(nh);
1399 0 : const TsnElector *te = agent->oper_db()->tsn_elector();
1400 0 : CompositeNH *cnh = dynamic_cast<CompositeNH *>(nh);
1401 0 : if (cnh && (cnh->composite_nh_type() == Composite::EVPN)) {
1402 0 : if (te->IsMaster() == false)
1403 0 : path->set_inactive(true);
1404 0 : nh = multicast_path->UpdateNH(agent, cnh, te);
1405 : }
1406 : }
1407 124 : ret = MulticastRoute::CopyPathParameters(agent,
1408 : path,
1409 1301 : vn_name_,
1410 : false,
1411 : vxlan_id_,
1412 1177 : ((label_ == MplsTable::kInvalidLabel) ? path->label() : label_),
1413 : tunnel_type_,
1414 1301 : nh, rt, ha_stale_);
1415 1301 : return ret;
1416 : }
1417 :
1418 2555 : bool MulticastRoute::CopyPathParameters(Agent *agent,
1419 : AgentPath *path,
1420 : const std::string &vn_name,
1421 : bool unresolved,
1422 : uint32_t vxlan_id,
1423 : uint32_t label,
1424 : uint32_t tunnel_type,
1425 : NextHop *nh,
1426 : const AgentRoute *rt,
1427 : bool ha_stale) {
1428 2555 : VnListType dest_vn_list;
1429 2555 : dest_vn_list.insert(vn_name);
1430 2555 : path->set_dest_vn_list(dest_vn_list);
1431 2555 : path->set_unresolved(unresolved);
1432 2555 : path->set_vxlan_id(vxlan_id);
1433 3933 : if ((path->peer() != agent->local_vm_peer()) &&
1434 1378 : (path->peer() != agent->local_peer()))
1435 1254 : path->set_label(label);
1436 :
1437 : //Setting of tunnel is only for simulated TOR.
1438 2555 : path->set_tunnel_bmap(tunnel_type);
1439 : TunnelType::Type new_tunnel_type =
1440 2555 : TunnelType::ComputeType(tunnel_type);
1441 2555 : if (new_tunnel_type == TunnelType::VXLAN &&
1442 : vxlan_id == VxLanTable::kInvalidvxlan_id) {
1443 0 : new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
1444 : }
1445 :
1446 2555 : if (path->tunnel_type() != new_tunnel_type) {
1447 66 : path->set_tunnel_type(new_tunnel_type);
1448 : }
1449 :
1450 2555 : uint32_t old_pref = path->path_preference().preference();
1451 2555 : if (ha_stale) {
1452 0 : if (old_pref != PathPreference::HA_STALE) {
1453 0 : path->path_preference_non_const().set_preference(PathPreference::HA_STALE);
1454 : }
1455 : } else {
1456 2555 : if (old_pref != PathPreference::LOW) {
1457 0 : path->path_preference_non_const().set_preference(PathPreference::LOW);
1458 : }
1459 : }
1460 :
1461 2555 : path->ChangeNH(agent, nh);
1462 :
1463 2555 : path->ResyncControlWord(rt);
1464 :
1465 2555 : return true;
1466 2555 : }
1467 :
1468 0 : bool MulticastRoute::CanDeletePath(Agent *agent, AgentPath *path,
1469 : const AgentRoute *rt) const {
1470 0 : return (vxlan_id() == path->vxlan_id());
1471 : }
1472 :
1473 446 : bool PathPreferenceData::AddChangePathExtended(Agent *agent, AgentPath *path,
1474 : const AgentRoute *rt) {
1475 446 : bool ret = false;
1476 : //ECMP flag will not be changed by path preference module,
1477 : //hence retain value in path
1478 446 : if (!path) {
1479 0 : return ret;
1480 : }
1481 :
1482 446 : path_preference_.set_ecmp(path->path_preference().ecmp());
1483 446 : path_preference_.set_dependent_ip(path->path_preference().dependent_ip());
1484 446 : path_preference_.set_vrf(path->path_preference().vrf());
1485 892 : if (path &&
1486 446 : path->path_preference() != path_preference_) {
1487 446 : path->set_path_preference(path_preference_);
1488 446 : ret = true;
1489 : }
1490 446 : return ret;
1491 : }
1492 :
1493 : // Subnet Route route data
1494 80 : IpamSubnetRoute::IpamSubnetRoute(DBRequest &nh_req,
1495 80 : const std::string &dest_vn_name) :
1496 : AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0),
1497 80 : dest_vn_name_(dest_vn_name) {
1498 80 : nh_req_.Swap(&nh_req);
1499 80 : }
1500 :
1501 80 : bool IpamSubnetRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
1502 : const AgentRoute *rt) {
1503 80 : agent->nexthop_table()->Process(nh_req_);
1504 160 : NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
1505 80 : FindActiveEntry(nh_req_.key.get()));
1506 80 : assert(nh);
1507 :
1508 80 : bool ret = false;
1509 :
1510 80 : if (path->ChangeNH(agent, nh) == true) {
1511 80 : ret = true;
1512 : }
1513 80 : path->set_is_subnet_discard(true);
1514 :
1515 80 : VnListType dest_vn_list;
1516 80 : dest_vn_list.insert(dest_vn_name_);
1517 80 : if (path->dest_vn_list() != dest_vn_list) {
1518 80 : path->set_dest_vn_list(dest_vn_list);
1519 80 : ret = true;
1520 : }
1521 :
1522 : //Resync of subnet route is needed for identifying if arp flood flag
1523 : //needs to be enabled for all the smaller subnets present w.r.t. this subnet
1524 : //route.
1525 80 : AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
1526 80 : assert((table->GetTableType() == Agent::INET4_UNICAST) ||
1527 : (table->GetTableType() == Agent::INET6_UNICAST));
1528 :
1529 80 : InetUnicastAgentRouteTable *uc_rt_table =
1530 : static_cast<InetUnicastAgentRouteTable *>(table);
1531 80 : const InetUnicastRouteEntry *uc_rt =
1532 : static_cast<const InetUnicastRouteEntry *>(rt);
1533 80 : uc_rt_table->ResyncSubnetRoutes(uc_rt, true);
1534 80 : return ret;
1535 80 : }
1536 :
1537 80 : bool IpamSubnetRoute::UpdateRoute(AgentRoute *rt) {
1538 80 : InetUnicastRouteEntry *uc_rt = static_cast<InetUnicastRouteEntry *>(rt);
1539 :
1540 80 : return uc_rt->UpdateRouteFlags(true, false, false);
1541 : }
1542 :
1543 : ///////////////////////////////////////////////
1544 : // Sandesh routines below (route_sandesh.cc)
1545 : //////////////////////////////////////////////
1546 : //TODO make it generic
1547 0 : void UnresolvedNH::HandleRequest() const {
1548 :
1549 0 : VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromId(0);
1550 0 : if (!vrf) {
1551 0 : ErrorResp *resp = new ErrorResp();
1552 0 : resp->set_context(context());
1553 0 : resp->Response();
1554 0 : return;
1555 : }
1556 :
1557 0 : int count = 0;
1558 0 : std::string empty("");
1559 : AgentRouteTable *rt_table = static_cast<AgentRouteTable *>
1560 0 : (vrf->GetInet4UnicastRouteTable());
1561 0 : NhListResp *resp = new NhListResp();
1562 :
1563 : //TODO - Convert inet4ucroutetable to agentroutetable
1564 0 : AgentRouteTable::UnresolvedNHTree::const_iterator it;
1565 0 : it = rt_table->unresolved_nh_begin();
1566 0 : for (;it != rt_table->unresolved_nh_end(); it++) {
1567 0 : count++;
1568 0 : const NextHop *nh = *it;
1569 0 : nh->DBEntrySandesh(resp, empty);
1570 0 : if (count == 1) {
1571 0 : resp->set_context(context()+"$");
1572 0 : resp->Response();
1573 0 : count = 0;
1574 0 : resp = new NhListResp();
1575 : }
1576 : }
1577 :
1578 0 : resp->set_context(context());
1579 0 : resp->Response();
1580 0 : return;
1581 0 : }
1582 :
1583 : //TODO IMplement filltrace in path class
1584 14962 : void AgentRoute::FillTrace(RouteInfo &rt_info, Trace event,
1585 : const AgentPath *path) const {
1586 14962 : Agent *agent = static_cast<AgentRouteTable *>(get_table())->agent();
1587 14962 : rt_info.set_ip(ToString());
1588 14962 : rt_info.set_vrf(vrf()->GetName());
1589 :
1590 14962 : switch(event) {
1591 1769 : case ADD:{
1592 1769 : rt_info.set_op("ADD");
1593 1769 : break;
1594 : }
1595 :
1596 1769 : case DEL: {
1597 1769 : rt_info.set_op("DELETE");
1598 1769 : break;
1599 : }
1600 :
1601 11424 : case ADD_PATH:
1602 : case DELETE_PATH:
1603 : case STALE_PATH:
1604 : case CHANGE_PATH: {
1605 11424 : if (event == ADD_PATH) {
1606 2598 : rt_info.set_op("PATH ADD");
1607 8826 : } else if (event == CHANGE_PATH) {
1608 6228 : rt_info.set_op("PATH CHANGE");
1609 2598 : } else if (event == DELETE_PATH) {
1610 2598 : rt_info.set_op("PATH DELETE");
1611 0 : } else if (event == STALE_PATH) {
1612 0 : rt_info.set_op("PATH STALE");
1613 : }
1614 :
1615 11424 : if (path == NULL) {
1616 0 : rt_info.set_nh_type("<NULL>");
1617 0 : break;
1618 : }
1619 :
1620 11424 : if (path->peer()) {
1621 11424 : rt_info.set_peer(path->peer()->GetName());
1622 : }
1623 11424 : rt_info.set_ecmp(path->path_preference().ecmp());
1624 11424 : const NextHop *nh = path->ComputeNextHop(agent);
1625 11424 : if (nh == NULL) {
1626 0 : rt_info.set_nh_type("<NULL>");
1627 0 : break;
1628 : }
1629 :
1630 11424 : switch (nh->GetType()) {
1631 151 : case NextHop::TUNNEL: {
1632 151 : const TunnelNH *tun = static_cast<const TunnelNH *>(nh);
1633 151 : rt_info.set_nh_type("TUNNEL");
1634 151 : rt_info.set_dest_server(tun->GetDip()->to_string());
1635 151 : rt_info.set_dest_server_vrf(tun->GetVrf()->GetName());
1636 151 : break;
1637 : }
1638 :
1639 12 : case NextHop::ARP:{
1640 12 : rt_info.set_nh_type("DIRECT");
1641 12 : break;
1642 : }
1643 :
1644 0 : case NextHop::NDP:{
1645 0 : rt_info.set_nh_type("DIRECT");
1646 0 : break;
1647 : }
1648 :
1649 6542 : case NextHop::INTERFACE: {
1650 6542 : const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
1651 6542 : rt_info.set_nh_type("INTERFACE");
1652 6542 : rt_info.set_intf(intf_nh->GetInterface()->name());
1653 6542 : break;
1654 : }
1655 :
1656 28 : case NextHop::RECEIVE: {
1657 28 : const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(nh);
1658 28 : rt_info.set_nh_type("RECEIVE");
1659 28 : rt_info.set_intf(rcv_nh->GetInterface()->name());
1660 28 : break;
1661 : }
1662 :
1663 2265 : case NextHop::DISCARD: {
1664 2265 : rt_info.set_nh_type("DISCARD");
1665 2265 : break;
1666 : }
1667 :
1668 0 : case NextHop::VLAN: {
1669 0 : rt_info.set_nh_type("VLAN");
1670 0 : break;
1671 : }
1672 :
1673 4 : case NextHop::RESOLVE: {
1674 4 : rt_info.set_nh_type("RESOLVE");
1675 4 : break;
1676 : }
1677 :
1678 1509 : case NextHop::COMPOSITE: {
1679 1509 : rt_info.set_nh_type("COMPOSITE");
1680 1509 : break;
1681 : }
1682 :
1683 913 : case NextHop::L2_RECEIVE: {
1684 913 : rt_info.set_nh_type("L2_RECEIVE");
1685 913 : break;
1686 : }
1687 :
1688 0 : case NextHop::PBB: {
1689 0 : const PBBNH *pbb_nh = static_cast<const PBBNH *>(nh);
1690 0 : rt_info.set_nh_type("PBB");
1691 0 : rt_info.set_mac(pbb_nh->dest_bmac().ToString());
1692 0 : if (pbb_nh->vrf()) {
1693 0 : rt_info.set_dest_server_vrf(pbb_nh->vrf()->GetName());
1694 : }
1695 0 : break;
1696 : }
1697 :
1698 0 : case NextHop::VRF: {
1699 0 : const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
1700 0 : rt_info.set_nh_type("VRF");
1701 0 : rt_info.set_vrf_nh_name(vrf_nh->GetVrf()->GetName());
1702 0 : break;
1703 : }
1704 :
1705 0 : default:
1706 0 : assert(0);
1707 : break;
1708 : }
1709 11424 : break;
1710 : }
1711 : }
1712 14962 : }
1713 :
1714 4212 : void AgentPath::GetDestinationVnList(std::vector<std::string> *vn_list) const {
1715 4212 : for (VnListType::const_iterator vnit = dest_vn_list().begin();
1716 8422 : vnit != dest_vn_list().end(); ++vnit) {
1717 4210 : vn_list->push_back(*vnit);
1718 : }
1719 4212 : }
1720 :
1721 0 : void AgentPath::SetSandeshData(PathSandeshData &pdata) const {
1722 0 : const NextHop *nh = nexthop();
1723 0 : if (nh != NULL) {
1724 0 : nh->SetNHSandeshData(pdata.nh);
1725 : }
1726 0 : pdata.set_peer(const_cast<Peer *>(peer())->GetName());
1727 0 : std::vector<std::string> vn_list;
1728 0 : GetDestinationVnList(&vn_list);
1729 0 : pdata.set_dest_vn_list(vn_list);
1730 0 : pdata.set_origin_vn(origin_vn());
1731 0 : pdata.set_unresolved(unresolved() ? "true" : "false");
1732 :
1733 0 : if (!gw_ip().is_unspecified()) {
1734 0 : pdata.set_gw_ip(gw_ip().to_string());
1735 0 : pdata.set_vrf(vrf_name());
1736 : }
1737 :
1738 0 : if (ecmp_suppressed()) {
1739 0 : pdata.set_ecmp_suppressed(true);
1740 : }
1741 :
1742 0 : pdata.set_sg_list(sg_list());
1743 0 : pdata.set_communities(communities());
1744 0 : pdata.set_tag_list(tag_list());
1745 0 : pdata.set_vxlan_id(vxlan_id());
1746 0 : pdata.set_label(label());
1747 0 : if (nh != NULL && nh->GetType() == NextHop::PBB) {
1748 0 : const PBBNH *pbb_nh = static_cast<const PBBNH *>(nh);
1749 0 : if (pbb_nh->child_nh() != NULL) {
1750 0 : const TunnelNH *tun_nh = dynamic_cast<const TunnelNH *>(pbb_nh->child_nh());
1751 0 : if (tun_nh != NULL) {
1752 0 : pdata.set_active_tunnel_type((tun_nh->GetTunnelType()).ToString());
1753 : }
1754 : }
1755 : } else {
1756 0 : pdata.set_active_tunnel_type(
1757 0 : TunnelType(tunnel_type()).ToString());
1758 : }
1759 0 : pdata.set_supported_tunnel_type(
1760 0 : TunnelType::GetString(tunnel_bmap()));
1761 0 : PathPreferenceSandeshData path_preference_data;
1762 0 : path_preference_data.set_sequence(path_preference_.sequence());
1763 0 : path_preference_data.set_preference(path_preference_.preference());
1764 0 : path_preference_data.set_ecmp(path_preference_.is_ecmp());
1765 0 : if ((peer()->GetType() != Peer::BGP_PEER) && (peer()->GetType() != Peer::ECMP_PEER )) {
1766 0 : path_preference_data.set_wait_for_traffic(
1767 0 : path_preference_.wait_for_traffic());
1768 : }
1769 0 : if (path_preference_.dependent_ip().is_unspecified() == false) {
1770 0 : std::ostringstream str;
1771 0 : str << path_preference_.vrf() << " : " <<path_preference_.dependent_ip().to_string();
1772 0 : path_preference_data.set_dependent_ip(str.str());
1773 0 : }
1774 0 : pdata.set_path_preference_data(path_preference_data);
1775 0 : pdata.set_active_label(GetActiveLabel());
1776 0 : if (peer()->GetType() == Peer::MAC_VM_BINDING_PEER) {
1777 0 : const MacVmBindingPath *dhcp_path =
1778 : static_cast<const MacVmBindingPath *>(this);
1779 0 : pdata.set_flood_dhcp(dhcp_path->flood_dhcp() ? "true" : "false");
1780 0 : pdata.set_vm_name(dhcp_path->vm_interface()->ToString());
1781 : }
1782 0 : std::vector<std::string> string_vector;
1783 0 : ecmp_load_balance_.GetStringVector(string_vector);
1784 : std::vector<std::string>::iterator string_vector_iter =
1785 0 : string_vector.begin();
1786 0 : std::stringstream ss;
1787 0 : while (string_vector_iter != string_vector.end()) {
1788 0 : ss << (*string_vector_iter);
1789 0 : ss << ",";
1790 0 : string_vector_iter++;
1791 : }
1792 0 : pdata.set_ecmp_hashing_fields(ss.str());
1793 0 : pdata.set_peer_sequence_number(peer_sequence_number());
1794 0 : const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer());
1795 0 : bool is_stale = false;
1796 0 : if (bgp_peer) {
1797 0 : if (peer_sequence_number() < bgp_peer->ChannelSequenceNumber())
1798 0 : is_stale = true;
1799 : }
1800 0 : pdata.set_stale(is_stale);
1801 0 : pdata.set_etree_leaf(etree_leaf());
1802 0 : pdata.set_layer2_control_word(layer2_control_word());
1803 0 : pdata.set_inactive(inactive());
1804 0 : }
1805 :
1806 58 : void AgentPath::set_local_ecmp_mpls_label(MplsLabel *mpls) {
1807 58 : local_ecmp_mpls_label_.reset(mpls);
1808 58 : }
1809 :
1810 2380 : bool AgentPath::dest_vn_match(const std::string &vn) const {
1811 2380 : if (dest_vn_list_.find(vn) != dest_vn_list_.end())
1812 2366 : return true;
1813 14 : return false;
1814 : }
1815 :
1816 641 : const MplsLabel* AgentPath::local_ecmp_mpls_label() const {
1817 641 : return local_ecmp_mpls_label_.get();
1818 : }
1819 :
1820 : //In case of composite NH in fabric VRF, if BGP path has router
1821 : //id of compute node then copy the ECMP peer or local VM peer path
1822 : //to composite NH.
1823 : //In case of overlay mode MPLS label was used to frame local nexthop
1824 : //list which is not feasible in this fabric VRF
1825 0 : void AgentPath::CopyLocalPath(CompositeNHKey *composite_nh_key,
1826 : const AgentPath *local_path) {
1827 :
1828 0 : if (local_path == NULL) {
1829 0 : return;
1830 : }
1831 :
1832 0 : DBEntryBase::KeyPtr key_nh = local_path->nexthop()->GetDBRequestKey();
1833 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key_nh.get());
1834 0 : nh_key->SetPolicy(false);
1835 0 : std::unique_ptr<const NextHopKey> nh_key_p(nh_key->Clone());
1836 :
1837 0 : ComponentNHKeyList comp_nh_list;
1838 0 : if (nh_key_p->GetType() == NextHop::COMPOSITE) {
1839 : //Append the list of component NH list from local ecmp peer
1840 0 : const CompositeNHKey *comp_nh_key =
1841 : static_cast<const CompositeNHKey *>(nh_key);
1842 0 : comp_nh_list = comp_nh_key->component_nh_key_list();
1843 : } else {
1844 : //Append the interface NH to composite NH list
1845 0 : ComponentNHKeyPtr new_comp_nh(new ComponentNHKey(0, std::move(nh_key_p)));
1846 0 : comp_nh_list.push_back(new_comp_nh);
1847 0 : }
1848 :
1849 0 : composite_nh_key->ReplaceLocalNexthop(comp_nh_list);
1850 0 : }
1851 :
1852 11 : bool AgentPath::ReorderCompositeNH(Agent *agent,
1853 : CompositeNHKey *composite_nh_key,
1854 : bool &comp_nh_policy,
1855 : const AgentPath *path) {
1856 11 : if (copy_local_path_) {
1857 0 : CopyLocalPath(composite_nh_key, path);
1858 : }
1859 :
1860 : //Find local composite mpls label, if present
1861 : //This has to be done, before expanding component NH
1862 59 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
1863 : composite_nh_key->component_nh_key_list()) {
1864 48 : if (component_nh_key.get() == NULL ||
1865 24 : component_nh_key->nh_key()->GetType() != NextHop::COMPOSITE) {
1866 24 : continue;
1867 : }
1868 : const CompositeNHKey *composite_key =
1869 0 : static_cast<const CompositeNHKey *>(component_nh_key->nh_key());
1870 : // composite NH, check composite nh type
1871 : // if it is not local ecmp , skip processing
1872 0 : if (composite_key->composite_nh_type() !=
1873 : Composite::LOCAL_ECMP) {
1874 0 : continue;
1875 : }
1876 : //Get mpls label allocated for this composite NH
1877 : MplsLabel *mpls = agent->mpls_table()->
1878 0 : FindMplsLabel(component_nh_key->label());
1879 0 : if (!mpls) {
1880 : //If a mpls label is deleted,
1881 : //wait for bgp to update latest list
1882 0 : local_ecmp_mpls_label_.reset(mpls);
1883 0 : return false;
1884 : }
1885 :
1886 0 : if (mpls == local_ecmp_mpls_label_.get()) {
1887 0 : break;
1888 : }
1889 0 : local_ecmp_mpls_label_.reset(mpls);
1890 : //Check if MPLS is pointing to same NH as mentioned in key list.
1891 : //It may so happen that by the time this request is serviced(say in
1892 : //case of remote route add from CN), mpls label ahs been re-used for
1893 : //some other purpose. If it is so then ignore the request and wait for
1894 : //another update.
1895 0 : const NextHopKey *nh_key_1 = component_nh_key->nh_key();
1896 0 : DBEntryBase::KeyPtr key = mpls->nexthop()->GetDBRequestKey();
1897 0 : const NextHopKey *nh_key_2 = static_cast<const NextHopKey*>(key.get());
1898 0 : if (nh_key_1->IsEqual(*nh_key_2) == false) {
1899 0 : return false;
1900 : }
1901 0 : break;
1902 24 : }
1903 :
1904 : //Make a copy of composite NH, so that aggregarate mpls
1905 : //label allocated for local composite ecmp is maintained
1906 : //as data in path
1907 11 : CompositeNHKey *comp_key = composite_nh_key->Clone();
1908 : //Reorder the keys so that, existing component NH maintain
1909 : //there previous position
1910 : //For example take a composite NH with members A, B, C
1911 : //in that exact order,If B gets deleted,
1912 : //the new composite NH created should be A <NULL> C in that order,
1913 : //irrespective of the order user passed it in
1914 11 : comp_nh_policy = composite_nh_key->Reorder(agent, label_,
1915 11 : ComputeNextHop(agent));
1916 : //Copy the unchanged component NH list to path data
1917 11 : set_composite_nh_key(comp_key);
1918 11 : return true;
1919 : }
1920 :
1921 0 : bool AgentPath::ChangeCompositeNH(Agent *agent,
1922 : CompositeNHKey *composite_nh_key) {
1923 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
1924 0 : nh_req.key.reset(composite_nh_key->Clone());
1925 0 : nh_req.data.reset(new CompositeNHData());
1926 :
1927 0 : NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
1928 0 : FindActiveEntry(composite_nh_key));
1929 0 : if (!nh) {
1930 0 : agent->nexthop_table()->Process(nh_req);
1931 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
1932 0 : FindActiveEntry(composite_nh_key));
1933 : }
1934 :
1935 : // NH can be NULL in the following scenario
1936 : // when VMI is deleted and it is the only member of VRF
1937 : // and VMI is part of AAP, then local ecmp route path
1938 : // is deleted from route and vrf delete would trigger route deletions
1939 : // in the VRF. while deleting the active path, import Nh from prev active
1940 : // path function copies the previous active path's NH to current active path
1941 : // and recalucalate composite NH based on composite nh key of current
1942 : // active path. if component nh key element of composite nh key is
1943 : // interface nh key which is already deleted then processing nh req would
1944 : // result NULL, in that case return false.
1945 : //assert(nh);
1946 0 : if (nh == NULL) {
1947 0 : return false;
1948 : }
1949 :
1950 0 : if (ChangeNH(agent, nh) == true) {
1951 0 : return true;
1952 : }
1953 0 : return false;
1954 0 : }
1955 :
1956 134 : const Ip4Address *AgentPath::NexthopIp(Agent *agent) const {
1957 134 : if (peer_ == NULL) {
1958 0 : return agent->router_ip_ptr();
1959 : }
1960 :
1961 134 : return peer_->NexthopIp(agent, this);
1962 : }
1963 :
1964 114 : MacVmBindingPath::MacVmBindingPath(const Peer *peer) :
1965 114 : AgentPath(peer, NULL), vm_interface_(NULL), flood_dhcp_(false) {
1966 114 : }
1967 :
1968 2173 : bool MacVmBindingPath::IsLess(const AgentPath &r_path) const {
1969 2173 : return peer()->IsLess(r_path.peer());
1970 : }
1971 :
1972 1335 : const NextHop *MacVmBindingPath::ComputeNextHop(Agent *agent) const {
1973 1335 : return nexthop();
1974 : }
1975 :
1976 114 : AgentPath *MacVmBindingPathData::CreateAgentPath(const Peer *peer,
1977 : AgentRoute *rt) const {
1978 114 : const Peer *mac_vm_binding_peer =
1979 : dynamic_cast<const Peer *>(peer);
1980 114 : assert(mac_vm_binding_peer != NULL);
1981 114 : return (new MacVmBindingPath(mac_vm_binding_peer));
1982 : }
1983 :
1984 996 : bool MacVmBindingPathData::AddChangePathExtended(Agent *agent, AgentPath *path,
1985 : const AgentRoute *rt) {
1986 996 : bool ret = false;
1987 : MacVmBindingPath *dhcp_path =
1988 996 : dynamic_cast<MacVmBindingPath *>(path);
1989 :
1990 996 : NextHop *nh = agent->nexthop_table()->discard_nh();
1991 996 : if (path->ChangeNH(agent, nh) == true)
1992 114 : ret = true;
1993 :
1994 996 : if (dhcp_path->flood_dhcp() != flood_dhcp_) {
1995 124 : dhcp_path->set_flood_dhcp(flood_dhcp_);
1996 124 : ret = true;
1997 : }
1998 :
1999 996 : if (dhcp_path->vm_interface() != vm_intf_) {
2000 647 : dhcp_path->set_vm_interface(vm_intf_);
2001 647 : ret = true;
2002 : }
2003 :
2004 996 : return ret;
2005 : }
2006 :
2007 0 : void AgentPath::UpdateEcmpHashFields(const Agent *agent,
2008 : const EcmpLoadBalance &ecmp_load_balance,
2009 : DBRequest &nh_req) {
2010 :
2011 0 : NextHop *nh = NULL;
2012 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
2013 0 : FindActiveEntry(nh_req.key.get()));
2014 0 : CompositeNH *cnh = dynamic_cast< CompositeNH *>(nh);
2015 0 : if (cnh) {
2016 0 : ecmp_hash_fields_.CalculateChangeInEcmpFields(ecmp_load_balance,
2017 : cnh->CompEcmpHashFields());
2018 : } else {
2019 0 : agent->nexthop_table()->Process(nh_req);
2020 0 : nh = static_cast<NextHop *>(agent->nexthop_table()->
2021 0 : FindActiveEntry(nh_req.key.get()));
2022 0 : CompositeNH *cnh = static_cast< CompositeNH *>(nh);
2023 0 : if (cnh) {
2024 0 : ecmp_hash_fields_.CalculateChangeInEcmpFields(ecmp_load_balance,
2025 : cnh->CompEcmpHashFields());
2026 : }
2027 : }
2028 0 : }
2029 :
2030 139 : void AgentPath::ResetEcmpHashFields() {
2031 139 : ecmp_hash_fields_.Reset();
2032 139 : }
2033 :
2034 4064 : bool AgentPath::ResyncControlWord(const AgentRoute *rt) {
2035 : const BridgeRouteEntry *bridge_rt =
2036 4064 : dynamic_cast<const BridgeRouteEntry *>(rt);
2037 4064 : if (!bridge_rt || rt->vrf() == NULL) {
2038 0 : return false;
2039 : }
2040 :
2041 4064 : if (layer2_control_word() != bridge_rt->vrf()->layer2_control_word()) {
2042 0 : set_layer2_control_word(bridge_rt->vrf()->layer2_control_word());
2043 0 : return true;
2044 : }
2045 :
2046 4064 : return false;
2047 : }
2048 :
2049 0 : EvpnRoutingPath::EvpnRoutingPath(const Peer *peer,
2050 : AgentRoute *rt,
2051 0 : VrfEntryConstRef routing_vrf) :
2052 0 : AgentPath(peer, rt), routing_vrf_(routing_vrf) {
2053 0 : l3_vrf_vxlan_id_ = routing_vrf.get()->vxlan_id();
2054 0 : }
2055 :
2056 0 : EvpnRoutingPath::~EvpnRoutingPath() {
2057 0 : }
2058 :
2059 0 : const VrfEntry *EvpnRoutingPath::routing_vrf() const {
2060 0 : return routing_vrf_.get();
2061 : }
2062 :
2063 0 : void EvpnRoutingPath::set_routing_vrf(const VrfEntry *vrf) {
2064 0 : routing_vrf_.reset(vrf);
2065 0 : }
2066 :
2067 0 : void EvpnRoutingPath::DeleteEvpnType5Route(Agent *agent,
2068 : const AgentRoute *rt) const {
2069 0 : const VrfEntry *l3_vrf = routing_vrf_.get();
2070 0 : if (!l3_vrf)
2071 0 : return;
2072 :
2073 : const InetUnicastRouteEntry *inet_rt =
2074 0 : dynamic_cast<const InetUnicastRouteEntry *>(rt);
2075 0 : if (!inet_rt) {
2076 0 : return;
2077 : }
2078 : const EvpnAgentRouteTable *evpn_table =
2079 0 : static_cast<EvpnAgentRouteTable *>(l3_vrf->GetEvpnRouteTable());
2080 0 : evpn_table->Delete(agent->local_vm_export_peer(), l3_vrf->GetName(),
2081 0 : MacAddress(), inet_rt->prefix_address(),
2082 0 : l3_vrf_vxlan_id_);
2083 : }
2084 :
2085 0 : EvpnRoutingData::EvpnRoutingData(DBRequest &nh_req,
2086 : const SecurityGroupList &sg_list,
2087 : const CommunityList &communities,
2088 : const PathPreference &path_preference,
2089 : const EcmpLoadBalance &ecmp_load_balance,
2090 : const TagList &tag_list,
2091 : VrfEntryConstRef vrf_entry,
2092 : uint32_t vxlan_id,
2093 : const VnListType& vn_list,
2094 0 : const std::string& origin_vn):
2095 : AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0),
2096 0 : sg_list_(sg_list),
2097 0 : communities_(communities),
2098 0 : path_preference_(path_preference),
2099 0 : ecmp_load_balance_(ecmp_load_balance),
2100 0 : tag_list_(tag_list),
2101 0 : routing_vrf_(vrf_entry), vxlan_id_(vxlan_id),
2102 0 : dest_vn_list_(vn_list),
2103 0 : origin_vn_(origin_vn) {
2104 0 : nh_req_.Swap(&nh_req);
2105 0 : }
2106 :
2107 0 : AgentPath *EvpnRoutingData::CreateAgentPath(const Peer *peer,
2108 : AgentRoute *rt) const {
2109 0 : return (new EvpnRoutingPath(peer, rt, routing_vrf_));
2110 : }
2111 :
2112 0 : bool EvpnRoutingData::AddChangePathExtended(Agent *agent,
2113 : AgentPath *path,
2114 : const AgentRoute *rt) {
2115 0 : bool ret = false;
2116 0 : EvpnRoutingPath *evpn_path = static_cast<EvpnRoutingPath *>(path);
2117 :
2118 : //Process nexthop
2119 0 : agent->nexthop_table()->Process(nh_req_);
2120 0 : NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
2121 0 : FindActiveEntry(nh_req_.key.get()));
2122 :
2123 0 : InterfaceNH *intf_nh = dynamic_cast<InterfaceNH *>(nh);
2124 0 : if (intf_nh) {
2125 0 : intf_nh->set_delete_on_zero_refcount(true);
2126 : }
2127 0 : if (routing_vrf_.get() != evpn_path->routing_vrf()) {
2128 : //Remove from old vrf
2129 0 : evpn_path->DeleteEvpnType5Route(agent, rt);
2130 0 : evpn_path->set_routing_vrf(routing_vrf_.get());
2131 0 : ret = true;
2132 : }
2133 :
2134 0 : if (path->ChangeNH(agent, nh) == true) {
2135 0 : ret = true;
2136 : }
2137 :
2138 0 : if (sg_list_ != path->sg_list()) {
2139 0 : path->set_sg_list(sg_list_);
2140 0 : ret = true;
2141 : }
2142 :
2143 : /* Setting the origin_vn in the route path */
2144 0 : if (path->origin_vn() != origin_vn_) {
2145 0 : path->set_origin_vn(origin_vn_);
2146 0 : ret = true;
2147 : }
2148 :
2149 : // Set dest vn
2150 0 : path->set_dest_vn_list(dest_vn_list_);
2151 :
2152 0 : if (communities_ != path->communities()) {
2153 0 : path->set_communities(communities_);
2154 0 : ret =true;
2155 : }
2156 :
2157 0 : if (path_preference_ != path->path_preference()) {
2158 0 : path->set_path_preference(path_preference_);
2159 0 : ret = true;
2160 : }
2161 :
2162 0 : if (ecmp_load_balance_ != path->ecmp_load_balance()) {
2163 0 : path->set_ecmp_load_balance(ecmp_load_balance_);
2164 0 : ret =true;
2165 : }
2166 :
2167 0 : if (tag_list_ != path->tag_list()) {
2168 0 : path->set_tag_list(tag_list_);
2169 0 : ret =true;
2170 : }
2171 :
2172 0 : path->set_tunnel_type(TunnelType::VXLAN);
2173 0 : path->set_tunnel_bmap(TunnelType::VxlanType());
2174 0 : path->set_vxlan_id(vxlan_id_);
2175 :
2176 0 : return ret;
2177 : }
2178 :
2179 0 : bool EvpnRoutingData::CanDeletePath(Agent *agent, AgentPath *path,
2180 : const AgentRoute *rt) const {
2181 0 : EvpnRoutingPath *evpn_path = dynamic_cast<EvpnRoutingPath *>(path);
2182 0 : if (!evpn_path) {
2183 0 : return true;
2184 : }
2185 0 : if (rt->vrf() != evpn_path->routing_vrf()) {
2186 : //Remove from old vrf
2187 0 : evpn_path->DeleteEvpnType5Route(agent, rt);
2188 : }
2189 0 : return true;
2190 : }
2191 0 : bool EvpnRoutingData::UpdateRoute(AgentRoute *rt) {
2192 : InetUnicastRouteEntry *uc_rt =
2193 0 : dynamic_cast<InetUnicastRouteEntry *>(rt);
2194 0 : if (!uc_rt) {
2195 0 : return false;
2196 : }
2197 0 : return uc_rt->UpdateRouteFlags(false, false, true);
2198 : }
2199 0 : AgentPathEcmpComponent::AgentPathEcmpComponent(IpAddress addr, uint32_t label,
2200 0 : AgentRoute *rt):
2201 0 : addr_(addr), label_(label), dependent_rt_(rt) {}
2202 :
|