diff --git a/src/vnsw/agent/controller/controller_peer.cc b/src/vnsw/agent/controller/controller_peer.cc index 4728c6b2580..bba42f5a097 100644 --- a/src/vnsw/agent/controller/controller_peer.cc +++ b/src/vnsw/agent/controller/controller_peer.cc @@ -656,6 +656,7 @@ void AgentXmppChannel::AddEcmpRoute(string vrf_name, IpAddress prefix_addr, } ComponentNHKeyList comp_nh_list; + bool comp_nh_policy = false; for (uint32_t i = 0; i < item->entry.next_hops.next_hop.size(); i++) { std::string nexthop_addr = item->entry.next_hops.next_hop[i].address; @@ -689,7 +690,8 @@ void AgentXmppChannel::AddEcmpRoute(string vrf_name, IpAddress prefix_addr, return; } - DBEntryBase::KeyPtr key = mpls->nexthop()->GetDBRequestKey(); + const NextHop *mpls_nh = mpls->nexthop(); + DBEntryBase::KeyPtr key = mpls_nh->GetDBRequestKey(); NextHopKey *nh_key = static_cast(key.release()); if (nh_key->GetType() != NextHop::COMPOSITE) { //By default all component members of composite NH @@ -701,6 +703,9 @@ void AgentXmppChannel::AddEcmpRoute(string vrf_name, IpAddress prefix_addr, ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label, nh_key_ptr)); comp_nh_list.push_back(component_nh_key); + if (!comp_nh_policy) { + comp_nh_policy = mpls_nh->NexthopToInterfacePolicy(); + } } } else { encap = GetTypeBitmap @@ -718,7 +723,7 @@ void AgentXmppChannel::AddEcmpRoute(string vrf_name, IpAddress prefix_addr, // Build the NH request and then create route data to be passed DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); - nh_req.key.reset(new CompositeNHKey(Composite::ECMP, false, + nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy, comp_nh_list, vrf_name)); nh_req.data.reset(new CompositeNHData()); ControllerEcmpRoute *data = diff --git a/src/vnsw/agent/controller/controller_route_path.cc b/src/vnsw/agent/controller/controller_route_path.cc index 62b86b0e2ad..83fb5cb200a 100644 --- a/src/vnsw/agent/controller/controller_route_path.cc +++ b/src/vnsw/agent/controller/controller_route_path.cc @@ -35,8 +35,13 @@ bool ControllerEcmpRoute::AddChangePath(Agent *agent, AgentPath *path, CompositeNHKey *comp_key = static_cast(nh_req_.key.get()); //Reorder the component NH list, and add a reference to local composite mpls //label if any - if (path->ReorderCompositeNH(agent, comp_key) == false) + bool comp_nh_policy = comp_key->GetPolicy(); + bool new_comp_nh_policy = false; + if (path->ReorderCompositeNH(agent, comp_key, new_comp_nh_policy) == false) return false; + if (!comp_nh_policy) { + comp_key->SetPolicy(new_comp_nh_policy); + } return InetUnicastRouteEntry::ModifyEcmpPath(dest_addr_, plen_, vn_list_, label_, local_ecmp_nh_, vrf_name_, sg_list_, diff --git a/src/vnsw/agent/oper/agent_path.cc b/src/vnsw/agent/oper/agent_path.cc index d9d18e67de1..b74a2860acd 100644 --- a/src/vnsw/agent/oper/agent_path.cc +++ b/src/vnsw/agent/oper/agent_path.cc @@ -253,7 +253,9 @@ bool AgentPath::Sync(AgentRoute *sync_route) { composite_nh_key_.get() != NULL && local_ecmp_mpls_label_.get() != NULL) { boost::scoped_ptr composite_nh_key(composite_nh_key_->Clone()); - if (ReorderCompositeNH(agent, composite_nh_key.get())) { + bool comp_nh_policy = false; + if (ReorderCompositeNH(agent, composite_nh_key.get(), comp_nh_policy)) { + composite_nh_key->SetPolicy(comp_nh_policy); if (ChangeCompositeNH(agent, composite_nh_key.get())) { ret = true; } @@ -1269,7 +1271,8 @@ const MplsLabel* AgentPath::local_ecmp_mpls_label() const { } bool AgentPath::ReorderCompositeNH(Agent *agent, - CompositeNHKey *composite_nh_key) { + CompositeNHKey *composite_nh_key, + bool &comp_nh_policy) { //Find local composite mpls label, if present //This has to be done, before expanding component NH BOOST_FOREACH(ComponentNHKeyPtr component_nh_key, @@ -1317,7 +1320,8 @@ bool AgentPath::ReorderCompositeNH(Agent *agent, //in that exact order,If B gets deleted, //the new composite NH created should be A C in that order, //irrespective of the order user passed it in - composite_nh_key->Reorder(agent, label_, ComputeNextHop(agent)); + comp_nh_policy = composite_nh_key->Reorder(agent, label_, + ComputeNextHop(agent)); //Copy the unchanged component NH list to path data set_composite_nh_key(comp_key); return true; diff --git a/src/vnsw/agent/oper/agent_path.h b/src/vnsw/agent/oper/agent_path.h index e2304b21097..539d0178cb2 100644 --- a/src/vnsw/agent/oper/agent_path.h +++ b/src/vnsw/agent/oper/agent_path.h @@ -255,7 +255,8 @@ class AgentPath : public Path { CompositeNHKey* composite_nh_key() { return composite_nh_key_.get(); } - bool ReorderCompositeNH(Agent *agent, CompositeNHKey *nh); + bool ReorderCompositeNH(Agent *agent, CompositeNHKey *nh, + bool &comp_nh_policy); bool ChangeCompositeNH(Agent *agent, CompositeNHKey *nh); // Get nexthop-ip address to be used for path const Ip4Address *NexthopIp(Agent *agent) const; diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 0b50d2d338c..eb25e6a0698 100644 --- a/src/vnsw/agent/oper/inet_unicast_route.cc +++ b/src/vnsw/agent/oper/inet_unicast_route.cc @@ -449,15 +449,22 @@ AgentPath *InetUnicastRouteEntry::AllocateEcmpPath(Agent *agent, // Allocate a new label for the ECMP path uint32_t label = agent->mpls_table()->AllocLabel(); + const NextHop* path1_nh = path1->ComputeNextHop(agent); + bool composite_nh_policy = path1_nh->NexthopToInterfacePolicy(); + // Create Component NH to be added to ECMP path - DBEntryBase::KeyPtr key1 = path1->ComputeNextHop(agent)->GetDBRequestKey(); + DBEntryBase::KeyPtr key1 = path1_nh->GetDBRequestKey(); NextHopKey *nh_key1 = static_cast(key1.release()); std::auto_ptr nh_akey1(nh_key1); nh_key1->SetPolicy(false); ComponentNHKeyPtr component_nh_data1(new ComponentNHKey(path1->label(), nh_akey1)); - DBEntryBase::KeyPtr key2 = path2->ComputeNextHop(agent)->GetDBRequestKey(); + const NextHop* path2_nh = path2->ComputeNextHop(agent); + if (!composite_nh_policy) { + composite_nh_policy = path2_nh->NexthopToInterfacePolicy(); + } + DBEntryBase::KeyPtr key2 = path2_nh->GetDBRequestKey(); NextHopKey *nh_key2 = static_cast(key2.release()); std::auto_ptr nh_akey2(nh_key2); nh_key2->SetPolicy(false); @@ -472,21 +479,22 @@ AgentPath *InetUnicastRouteEntry::AllocateEcmpPath(Agent *agent, // It will also create CompositeNH if necessary DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); nh_req.key.reset(new CompositeNHKey(Composite::LOCAL_ECMP, - false, component_nh_list, + composite_nh_policy, component_nh_list, vrf()->GetName())); nh_req.data.reset(new CompositeNHData()); InetUnicastRouteEntry::ModifyEcmpPath(addr_, plen_, path2->dest_vn_list(), - label, true, vrf()->GetName(), - path2->sg_list(), - path2->communities(), - path2->path_preference(), - path2->tunnel_bmap(), - path2->ecmp_load_balance(), - nh_req, agent, path); + label, true, vrf()->GetName(), + path2->sg_list(), + path2->communities(), + path2->path_preference(), + path2->tunnel_bmap(), + path2->ecmp_load_balance(), + nh_req, agent, path); //Make MPLS label point to Composite NH - MplsLabel::CreateEcmpLabel(agent, label, Composite::LOCAL_ECMP, component_nh_list, + MplsLabel::CreateEcmpLabel(agent, label, Composite::LOCAL_ECMP, + composite_nh_policy, component_nh_list, vrf()->GetName()); RouteInfo rt_info; @@ -763,7 +771,8 @@ void InetUnicastRouteEntry::AppendEcmpPath(Agent *agent, AgentPath *ecmp_path = FindPath(agent->ecmp_peer()); assert(ecmp_path); - DBEntryBase::KeyPtr key = path->ComputeNextHop(agent)->GetDBRequestKey(); + const NextHop* path_nh = path->ComputeNextHop(agent); + DBEntryBase::KeyPtr key = path_nh->GetDBRequestKey(); NextHopKey *nh_key = static_cast(key.release()); std::auto_ptr nh_akey(nh_key); nh_key->SetPolicy(false); @@ -772,12 +781,14 @@ void InetUnicastRouteEntry::AppendEcmpPath(Agent *agent, ComponentNHKeyList component_nh_key_list; const CompositeNH *comp_nh = static_cast(ecmp_path->ComputeNextHop(agent)); - component_nh_key_list = comp_nh->AddComponentNHKey(comp_nh_key_ptr); - + bool composite_nh_policy = false; + component_nh_key_list = comp_nh->AddComponentNHKey(comp_nh_key_ptr, + composite_nh_policy); // Form the request for Inet4UnicastEcmpRoute and invoke AddChangePath DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); nh_req.key.reset(new CompositeNHKey(Composite::LOCAL_ECMP, - false, component_nh_key_list, + composite_nh_policy, + component_nh_key_list, vrf()->GetName())); nh_req.data.reset(new CompositeNHData()); @@ -791,7 +802,8 @@ void InetUnicastRouteEntry::AppendEcmpPath(Agent *agent, //Make MPLS label point to composite NH MplsLabel::CreateEcmpLabel(agent, ecmp_path->label(), Composite::LOCAL_ECMP, - component_nh_key_list, vrf()->GetName()); + composite_nh_policy, component_nh_key_list, + vrf()->GetName()); RouteInfo rt_info; FillTrace(rt_info, AgentRoute::CHANGE_PATH, path); @@ -811,24 +823,27 @@ bool InetUnicastRouteEntry::UpdateComponentNH(Agent *agent, return false; } //Build ComponentNHKey for new path - DBEntryBase::KeyPtr key = path->ComputeNextHop(agent)->GetDBRequestKey(); + const NextHop* path_nh = path->ComputeNextHop(agent); + DBEntryBase::KeyPtr key = path_nh->GetDBRequestKey(); NextHopKey *nh_key = static_cast(key.get()); nh_key->SetPolicy(false); ComponentNHKeyList component_nh_key_list; const CompositeNH *comp_nh = static_cast(ecmp_path->ComputeNextHop(agent)); + bool composite_nh_policy = false; bool updated = comp_nh->UpdateComponentNHKey(path->label(), nh_key, - component_nh_key_list); + component_nh_key_list, + composite_nh_policy); if (!updated) { return false; } - // Form the request for Inet4UnicastEcmpRoute and invoke AddChangePath DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); nh_req.key.reset(new CompositeNHKey(Composite::LOCAL_ECMP, - false, component_nh_key_list, + composite_nh_policy, + component_nh_key_list, vrf()->GetName())); nh_req.data.reset(new CompositeNHData()); @@ -843,7 +858,8 @@ bool InetUnicastRouteEntry::UpdateComponentNH(Agent *agent, //Make MPLS label point to updated composite NH MplsLabel::CreateEcmpLabel(agent, ecmp_path->label(), Composite::LOCAL_ECMP, - component_nh_key_list, vrf()->GetName()); + composite_nh_policy, component_nh_key_list, + vrf()->GetName()); RouteInfo rt_info; FillTrace(rt_info, AgentRoute::CHANGE_PATH, path); @@ -865,14 +881,16 @@ void InetUnicastRouteEntry::DeleteComponentNH(Agent *agent, AgentPath *path) { ComponentNHKeyPtr comp_nh_key_ptr(new ComponentNHKey(path->label(), nh_akey)); ComponentNHKeyList component_nh_key_list; + bool comp_nh_policy = false; const CompositeNH *comp_nh = static_cast(ecmp_path->ComputeNextHop(agent)); - component_nh_key_list = comp_nh->DeleteComponentNHKey(comp_nh_key_ptr); + component_nh_key_list = comp_nh->DeleteComponentNHKey(comp_nh_key_ptr, + comp_nh_policy); // Form the request for Inet4UnicastEcmpRoute and invoke AddChangePath DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE); nh_req.key.reset(new CompositeNHKey(Composite::LOCAL_ECMP, - false, component_nh_key_list, + comp_nh_policy, component_nh_key_list, vrf()->GetName())); nh_req.data.reset(new CompositeNHData()); @@ -889,7 +907,8 @@ void InetUnicastRouteEntry::DeleteComponentNH(Agent *agent, AgentPath *path) { //Make MPLS label point to composite NH MplsLabel::CreateEcmpLabel(agent, ecmp_path->label(), Composite::LOCAL_ECMP, - component_nh_key_list, vrf()->GetName()); + comp_nh_policy, component_nh_key_list, + vrf()->GetName()); RouteInfo rt_info; FillTrace(rt_info, AgentRoute::CHANGE_PATH, path); diff --git a/src/vnsw/agent/oper/mpls.cc b/src/vnsw/agent/oper/mpls.cc index 67538b877a5..1add8b26aca 100644 --- a/src/vnsw/agent/oper/mpls.cc +++ b/src/vnsw/agent/oper/mpls.cc @@ -202,7 +202,7 @@ void MplsLabel::CreateVPortLabel(const Agent *agent, } void MplsLabel::CreateEcmpLabel(const Agent *agent, - uint32_t label, COMPOSITETYPE type, + uint32_t label, COMPOSITETYPE type, bool policy, ComponentNHKeyList &component_nh_key_list, const std::string vrf_name) { DBRequest req; @@ -211,7 +211,7 @@ void MplsLabel::CreateEcmpLabel(const Agent *agent, MplsLabelKey *key = new MplsLabelKey(MplsLabel::VPORT_NH, label); req.key.reset(key); - MplsLabelData *data = new MplsLabelData(type, false, component_nh_key_list, + MplsLabelData *data = new MplsLabelData(type, policy, component_nh_key_list, vrf_name); req.data.reset(data); diff --git a/src/vnsw/agent/oper/mpls.h b/src/vnsw/agent/oper/mpls.h index 274a87d165a..512eb652251 100644 --- a/src/vnsw/agent/oper/mpls.h +++ b/src/vnsw/agent/oper/mpls.h @@ -55,7 +55,8 @@ class MplsLabel : AgentRefCount, public AgentDBEntry { bool policy, InterfaceNHFlags::Type type, const MacAddress &mac); - static void CreateEcmpLabel(const Agent *agent, uint32_t label, COMPOSITETYPE type, + static void CreateEcmpLabel(const Agent *agent, uint32_t label, + COMPOSITETYPE type, bool policy, ComponentNHKeyList &component_nh_key_list, const std::string vrf_name); // Delete MPLS Label entry diff --git a/src/vnsw/agent/oper/nexthop.cc b/src/vnsw/agent/oper/nexthop.cc index ec22e928f1f..cc2fccb4c98 100644 --- a/src/vnsw/agent/oper/nexthop.cc +++ b/src/vnsw/agent/oper/nexthop.cc @@ -216,6 +216,19 @@ void NextHop::FillObjectLogMac(const unsigned char *m, info.set_mac(mac); } +bool NextHop::NexthopToInterfacePolicy() const { + if (GetType() == NextHop::INTERFACE) { + const InterfaceNH *intf_nh = + static_cast(this); + const VmInterface *intf = dynamic_cast + (intf_nh->GetInterface()); + if (intf && intf->policy_enabled()) { + return true; + } + } + return false; +} + std::auto_ptr NextHopTable::AllocEntry(const DBRequestKey *k) const { return std::auto_ptr(static_cast(AllocWithKey(k))); } @@ -1829,65 +1842,89 @@ void CompositeNHKey::erase(ComponentNHKeyPtr nh_key) { } bool CompositeNH::UpdateComponentNHKey(uint32_t label, NextHopKey *nh_key, - ComponentNHKeyList &component_nh_key_list) const { + ComponentNHKeyList &component_nh_key_list, bool &comp_nh_policy) const { bool ret = false; - ComponentNHKeyList::const_iterator it = component_nh_key_list_.begin(); - for (;it != component_nh_key_list_.end(); it++) { - //If there is a empty slot, in component key list retain the empty slot - //in new list - if ((*it) == NULL) { + comp_nh_policy = false; + BOOST_FOREACH(ComponentNHPtr it, component_nh_list_) { + if (it.get() == NULL) { ComponentNHKeyPtr dummy_ptr; dummy_ptr.reset(); component_nh_key_list.push_back(dummy_ptr); continue; } - const NextHopKey *lhs = (*it)->nh_key(); - uint32_t new_label = (*it)->label(); - if((*it) && (*it)->label() != label && lhs->IsEqual(*nh_key)) { + const ComponentNH *component_nh = it.get(); + uint32_t new_label = component_nh->label(); + DBEntryBase::KeyPtr key = component_nh->nh()->GetDBRequestKey(); + NextHopKey *lhs = static_cast(key.release()); + + if (new_label != label && lhs->IsEqual(*nh_key)) { new_label = label; ret = true; } - std::auto_ptr nh_akey(lhs->Clone()); - ComponentNHKeyPtr comp_nh_key_ptr(new ComponentNHKey(new_label, - nh_akey)); - component_nh_key_list.push_back(comp_nh_key_ptr); + std::auto_ptr nh_key_ptr(lhs); + ComponentNHKeyPtr component_nh_key( + new ComponentNHKey(new_label, nh_key_ptr)); + component_nh_key_list.push_back(component_nh_key); + if (!comp_nh_policy) { + comp_nh_policy = component_nh->nh()->NexthopToInterfacePolicy(); + } } return ret; } -ComponentNHKeyList CompositeNH::AddComponentNHKey(ComponentNHKeyPtr cnh) const { +ComponentNHKeyList CompositeNH::AddComponentNHKey(ComponentNHKeyPtr cnh, + bool &comp_nh_policy) const { Agent *agent = static_cast(get_table())->agent(); const NextHop *nh = static_cast(agent->nexthop_table()-> FindActiveEntry(cnh->nh_key())); assert(nh); ComponentNHKeyList component_nh_key_list = component_nh_key_list_; - ComponentNHList::const_iterator it = begin(); int index = 0; - //Make sure new entry is not already present - for (;it != end(); it++, index++) { - if((*it) && (*it)->nh() == nh) { - if ((*it)->label() == cnh->label()) { + + comp_nh_policy = false; + bool made_cnh_list = false; + BOOST_FOREACH(ComponentNHPtr it, component_nh_list_) { + const ComponentNH *component_nh = it.get(); + if (component_nh == NULL) { + index++; + continue; + } + if (component_nh->nh() == nh) { + if (component_nh->label() == cnh->label()) { //Entry already present, return old component nh key list + comp_nh_policy = PolicyEnabled(); return component_nh_key_list; } else { - /* If the label of VMI has changed (due to policy change), - * reset the position of the VMI in component_nh_key_list */ - if (nh && nh->GetType() == NextHop::INTERFACE) { + if (nh->GetType() == NextHop::INTERFACE) { component_nh_key_list[index] = cnh; - return component_nh_key_list; + made_cnh_list = true; + } + if (!comp_nh_policy) { + comp_nh_policy = nh->NexthopToInterfacePolicy(); } } + } else if (!comp_nh_policy) { + comp_nh_policy = component_nh->nh()->NexthopToInterfacePolicy(); + } + if (comp_nh_policy && made_cnh_list) { + break; } + index++; + } + + if (made_cnh_list) { + return component_nh_key_list; } bool inserted = false; + index = 0; ComponentNHKeyList::const_iterator key_it = component_nh_key_list.begin(); - for (;key_it != component_nh_key_list.end(); key_it++) { + for (;key_it != component_nh_key_list.end(); key_it++, index++) { //If there is a empty slot, in //component key list insert the element there. if ((*key_it) == NULL) { - component_nh_key_list.push_back(cnh); + component_nh_key_list[index] = cnh; inserted = true; break; } @@ -1897,11 +1934,16 @@ ComponentNHKeyList CompositeNH::AddComponentNHKey(ComponentNHKeyPtr cnh) const { if (inserted == false) { component_nh_key_list.push_back(cnh); } + comp_nh_policy = PolicyEnabled(); + if (!comp_nh_policy && (nh->GetType() == NextHop::INTERFACE)) { + comp_nh_policy = nh->NexthopToInterfacePolicy(); + } return component_nh_key_list; } ComponentNHKeyList -CompositeNH::DeleteComponentNHKey(ComponentNHKeyPtr cnh) const { +CompositeNH::DeleteComponentNHKey(ComponentNHKeyPtr cnh, + bool &comp_nh_new_policy) const { Agent *agent = static_cast(get_table())->agent(); const NextHop *nh = static_cast(agent->nexthop_table()-> FindActiveEntry(cnh->nh_key())); @@ -1910,12 +1952,31 @@ CompositeNH::DeleteComponentNHKey(ComponentNHKeyPtr cnh) const { ComponentNHKeyList component_nh_key_list = component_nh_key_list_; ComponentNHKeyPtr component_nh_key; ComponentNHList::const_iterator it = begin(); + comp_nh_new_policy = false; + bool removed = false; int index = 0; for (;it != end(); it++, index++) { ComponentNHKeyPtr dummy_ptr; dummy_ptr.reset(); if ((*it) && ((*it)->label() == cnh->label() && (*it)->nh() == nh)) { component_nh_key_list[index] = dummy_ptr; + removed = true; + } else { + /* Go through all the component Interface Nexthops of this + * CompositeNH to figure out the new policy status of this + * CompositeNH. Ignore the component NH being deleted while + * iterating. */ + if ((*it) && (*it)->nh() && !comp_nh_new_policy) { + /* If any one of component NH's interface has policy enabled, + * the policy-status of compositeNH is true. So we need to + * look only until we find the first Interface which has + * policy enabled */ + comp_nh_new_policy = (*it)->nh()->NexthopToInterfacePolicy(); + } + } + if (removed && comp_nh_new_policy) { + /* No need to iterate further if we done with both deleting key and + * figuring out policy-status */ break; } } @@ -1973,7 +2034,7 @@ bool CompositeNHKey::NextHopKeyIsLess(const NextHopKey &rhs) const { return false; } -void CompositeNHKey::ExpandLocalCompositeNH(Agent *agent) { +bool CompositeNHKey::ExpandLocalCompositeNH(Agent *agent) { uint32_t label = MplsTable::kInvalidLabel; //Find local composite ecmp label BOOST_FOREACH(ComponentNHKeyPtr component_nh_key, @@ -1990,32 +2051,46 @@ void CompositeNHKey::ExpandLocalCompositeNH(Agent *agent) { //No Local composite NH found if (label == MplsTable::kInvalidLabel) { - return; + return false; } MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(label); if (mpls == NULL) { - return; + return false; } - DBEntryBase::KeyPtr key = mpls->nexthop()->GetDBRequestKey(); - NextHopKey *nh_key = static_cast(key.get()); - assert(nh_key->GetType() == NextHop::COMPOSITE); - CompositeNHKey *local_composite_nh_key = - static_cast(nh_key); - //Insert individual entries - BOOST_FOREACH(ComponentNHKeyPtr component_nh_key, - local_composite_nh_key->component_nh_key_list()) { + const NextHop *mpls_nh = mpls->nexthop(); + assert(mpls_nh->GetType() == NextHop::COMPOSITE); + const CompositeNH *cnh = static_cast(mpls_nh); + + bool comp_nh_new_policy = false; + BOOST_FOREACH(ComponentNHPtr it, cnh->component_nh_list()) { + if (it.get() == NULL) { + ComponentNHKeyPtr dummy_ptr; + dummy_ptr.reset(); + insert(dummy_ptr); + continue; + } + const ComponentNH *component_nh = it.get(); + DBEntryBase::KeyPtr key = component_nh->nh()->GetDBRequestKey(); + NextHopKey *nh_key = static_cast(key.release()); + std::auto_ptr nh_key_ptr(nh_key); + ComponentNHKeyPtr component_nh_key( + new ComponentNHKey(component_nh->label(), nh_key_ptr)); insert(component_nh_key); + if (!comp_nh_new_policy) { + comp_nh_new_policy = component_nh->nh()->NexthopToInterfacePolicy(); + } } + return comp_nh_new_policy; } -void CompositeNHKey::Reorder(Agent *agent, +bool CompositeNHKey::Reorder(Agent *agent, uint32_t label, const NextHop *nh) { //Enqueue request to create Tunnel NH CreateTunnelNH(agent); //First expand local composite NH, if any - ExpandLocalCompositeNH(agent); + bool policy = ExpandLocalCompositeNH(agent); //Order the component NH entries, so that previous position of //component NH are maintained. //For example, if previous composite NH consisted of A, B and C @@ -2031,7 +2106,7 @@ void CompositeNHKey::Reorder(Agent *agent, //Then new composite NH has to be A, B, C, D in that order, such that //A, B, C nexthop retain there position if (!nh) { - return; + return policy; } if (nh->GetType() != NextHop::COMPOSITE) { @@ -2052,7 +2127,7 @@ void CompositeNHKey::Reorder(Agent *agent, insert(component_nh_key); insert(first_entry); } - return; + return policy; } CompositeNHKey *composite_nh_key; @@ -2076,6 +2151,7 @@ void CompositeNHKey::Reorder(Agent *agent, } //Copy over the list component_nh_key_list_ = composite_nh_key->component_nh_key_list(); + return policy; } ComponentNHKey::ComponentNHKey(int label, Composite::Type type, bool policy, diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index 9638c387f6a..0a1bc896f36 100644 --- a/src/vnsw/agent/oper/nexthop.h +++ b/src/vnsw/agent/oper/nexthop.h @@ -380,6 +380,7 @@ class NextHop : AgentRefCount, public AgentDBEntry { NextHopObjectLogInfo &info); static void FillObjectLogMac(const unsigned char *m, NextHopObjectLogInfo &info); + bool NexthopToInterfacePolicy() const; protected: void FillObjectLog(AgentLogEvent::type event, NextHopObjectLogInfo &info) const; @@ -1253,14 +1254,14 @@ class CompositeNHKey : public NextHopKey { const ComponentNHKeyList& component_nh_key_list() const { return component_nh_key_list_; } - void Reorder(Agent *agent, uint32_t label, const NextHop *nh); + bool Reorder(Agent *agent, uint32_t label, const NextHop *nh); void CreateTunnelNH(Agent *agent); void CreateTunnelNHReq(Agent *agent); void ChangeTunnelType(TunnelType::Type tunnel_type); COMPOSITETYPE composite_nh_type() const {return composite_nh_type_;} private: friend class CompositeNH; - void ExpandLocalCompositeNH(Agent *agent); + bool ExpandLocalCompositeNH(Agent *agent); void insert(ComponentNHKeyPtr nh_key); void erase(ComponentNHKeyPtr nh_key); bool find(ComponentNHKeyPtr nh_key); @@ -1355,13 +1356,14 @@ class CompositeNH : public NextHop { return; } uint32_t GetRemoteLabel(const Ip4Address &ip) const; - ComponentNHKeyList AddComponentNHKey(ComponentNHKeyPtr - component_nh_key) const; + ComponentNHKeyList AddComponentNHKey(ComponentNHKeyPtr component_nh_key, + bool &comp_nh_policy) const; ComponentNHKeyList DeleteComponentNHKey(ComponentNHKeyPtr - component_nh_key) const; + component_nh_key, + bool &comp_nh_new_policy) const; bool UpdateComponentNHKey(uint32_t label, NextHopKey *nh_key, - ComponentNHKeyList &component_nh_key_list) const; - ComponentNHList& component_nh_list() { + ComponentNHKeyList &component_nh_key_list, bool &comp_nh_policy) const; + const ComponentNHList& component_nh_list() const { return component_nh_list_; } const ComponentNHKeyList& component_nh_key_list() const { diff --git a/src/vnsw/agent/oper/test/test_intf_policy.cc b/src/vnsw/agent/oper/test/test_intf_policy.cc index e5e3046edfa..d7f3c421c71 100644 --- a/src/vnsw/agent/oper/test/test_intf_policy.cc +++ b/src/vnsw/agent/oper/test/test_intf_policy.cc @@ -723,7 +723,7 @@ TEST_F(PolicyTest, EcmpNH_1) { EXPECT_TRUE(nh->GetType() == NextHop::COMPOSITE); comp_nh = static_cast(nh); EXPECT_TRUE(comp_nh->ComponentNHCount() == 2); - EXPECT_TRUE(comp_nh->PolicyEnabled() == false); + EXPECT_TRUE(comp_nh->PolicyEnabled() == true); uint32_t label1 = comp_nh->Get(0)->label(); uint32_t label2 = comp_nh->Get(1)->label(); diff --git a/src/vnsw/agent/test/test_ecmp_nh.cc b/src/vnsw/agent/test/test_ecmp_nh.cc index 775fd5a1c4c..555818063a4 100644 --- a/src/vnsw/agent/test/test_ecmp_nh.cc +++ b/src/vnsw/agent/test/test_ecmp_nh.cc @@ -217,6 +217,9 @@ TEST_F(EcmpNhTest, EcmpNH_2) { const NextHop *nh = rt->GetActiveNextHop(); EXPECT_TRUE(nh->GetType() == NextHop::INTERFACE); EXPECT_TRUE(nh->PolicyEnabled() == true); + VmInterface *intf = VmInterfaceGet(input1[0].intf_id); + EXPECT_TRUE(intf != NULL); + EXPECT_TRUE(intf->policy_enabled()); //Second VM added, route should point to composite NH CreateVmportWithEcmp(input2, 1); @@ -224,7 +227,7 @@ TEST_F(EcmpNhTest, EcmpNH_2) { nh = rt->GetActiveNextHop(); EXPECT_TRUE(nh->GetType() == NextHop::COMPOSITE); const CompositeNH *comp_nh = static_cast(nh); - EXPECT_TRUE(comp_nh->PolicyEnabled() == false); + EXPECT_TRUE(comp_nh->PolicyEnabled() == true); EXPECT_TRUE(comp_nh->ComponentNHCount() == 2); const InterfaceNH *intf_nh = static_cast(comp_nh->Get(0)->nh()); EXPECT_TRUE(intf_nh->PolicyEnabled() == false); @@ -245,7 +248,7 @@ TEST_F(EcmpNhTest, EcmpNH_2) { comp_nh = static_cast(rt->GetActiveNextHop()); EXPECT_TRUE(comp_nh->GetType() == NextHop::COMPOSITE); EXPECT_TRUE(comp_nh->ComponentNHCount() == 5); - EXPECT_TRUE(comp_nh->PolicyEnabled() == false); + EXPECT_TRUE(comp_nh->PolicyEnabled() == true); //Verify all the component NH have right label and nexthop ComponentNHList::const_iterator component_nh_it = @@ -305,7 +308,7 @@ TEST_F(EcmpNhTest, EcmpNH_2) { //Verify all the component NH have right label and nexthop comp_nh = static_cast(rt->GetActiveNextHop()); - EXPECT_TRUE(comp_nh->PolicyEnabled() == false); + EXPECT_TRUE(comp_nh->PolicyEnabled() == true); component_nh_it = comp_nh->begin(); intf_nh = static_cast((*component_nh_it)->nh()); EXPECT_TRUE(intf_nh->GetInterface()->name() == "vnet1");