diff --git a/src/vnsw/agent/oper/inet_unicast_route.cc b/src/vnsw/agent/oper/inet_unicast_route.cc index 0b50d2d338c..fbfe2e6b3c4 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); @@ -773,11 +782,16 @@ void InetUnicastRouteEntry::AppendEcmpPath(Agent *agent, 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 = comp_nh->PolicyEnabled(); + if (!composite_nh_policy) { + composite_nh_policy = path_nh->NexthopToInterfacePolicy(); + } // 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 +805,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,7 +826,8 @@ 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); @@ -825,10 +841,16 @@ bool InetUnicastRouteEntry::UpdateComponentNH(Agent *agent, return false; } + bool composite_nh_policy = comp_nh->PolicyEnabled(); + + if (!composite_nh_policy) { + composite_nh_policy = path_nh->NexthopToInterfacePolicy(); + } // 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 +865,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 +888,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 +914,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..4ec01412427 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))); } @@ -1901,7 +1914,8 @@ ComponentNHKeyList CompositeNH::AddComponentNHKey(ComponentNHKeyPtr cnh) const { } 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 +1924,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; } } diff --git a/src/vnsw/agent/oper/nexthop.h b/src/vnsw/agent/oper/nexthop.h index 9638c387f6a..7c82d589af4 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; @@ -1358,7 +1359,8 @@ class CompositeNH : public NextHop { ComponentNHKeyList AddComponentNHKey(ComponentNHKeyPtr component_nh_key) 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() { 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");