diff --git a/src/vnsw/agent/oper/path_preference.cc b/src/vnsw/agent/oper/path_preference.cc index 4ebfcb14765..3860166456f 100644 --- a/src/vnsw/agent/oper/path_preference.cc +++ b/src/vnsw/agent/oper/path_preference.cc @@ -338,6 +338,9 @@ void PathPreferenceSM::Process() { const AgentPath *path = static_cast(it.operator->()); if (path == local_path) { + if (path->path_preference().sequence() < sequence()) { + EnqueuePathChange(); + } continue; } //Get best preference and sequence no from all BGP peer diff --git a/src/vnsw/agent/oper/test/test_aap.cc b/src/vnsw/agent/oper/test/test_aap.cc index df3b48fc039..ae4e467a3cb 100644 --- a/src/vnsw/agent/oper/test/test_aap.cc +++ b/src/vnsw/agent/oper/test/test_aap.cc @@ -309,6 +309,7 @@ TEST_F(TestAap, EvpnRoute_3) { EXPECT_TRUE(path->path_preference().wait_for_traffic() == false); } #endif + //Just add a local path, verify that sequence no gets initialized to 0 TEST_F(TestAap, StateMachine_1) { Ip4Address ip = Ip4Address::from_string("1.1.1.1"); @@ -865,6 +866,49 @@ TEST_F(TestAap, StateMachine_15) { WAIT_FOR(1000, 1000, (path->path_preference().wait_for_traffic() == true)); } +TEST_F(TestAap, StateMachine_16) { + Ip4Address ip = Ip4Address::from_string("10.10.10.10"); + MacAddress mac("0a:0b:0c:0d:0e:0f"); + + VmInterface *vm_intf = static_cast(VmPortGet(1)); + AddAap("intf1", 1, ip, mac.ToString()); + EXPECT_TRUE(RouteFind("vrf1", ip, 32)); + EXPECT_TRUE(EvpnRouteGet("vrf1", mac, ip, 0)); + EXPECT_TRUE(vm_intf->allowed_address_pair_list().list_.size() == 1); + + client->WaitForIdle(); + + EvpnRouteEntry *rt = EvpnRouteGet("vrf1", mac, ip, 0); + const AgentPath *path = rt->FindPath(vm_intf->peer()); + + Agent::GetInstance()->oper_db()->route_preference_module()-> + EnqueueTrafficSeen(ip, 32, vm_intf->id(), vm_intf->vrf()->vrf_id(), + mac); + client->WaitForIdle(); + EXPECT_TRUE(path->path_preference().sequence() == 1); + EXPECT_TRUE(path->path_preference().preference() == PathPreference::HIGH); + EXPECT_TRUE(path->path_preference().ecmp() == false); + EXPECT_TRUE(path->path_preference().wait_for_traffic() == false); + + AddSg("sg1", 1); + AddAcl("acl1", 1); + AddLink("security-group", "sg1", "access-control-list", "acl1"); + AddLink("virtual-machine-interface", "intf1", "security-group", "sg1"); + client->WaitForIdle(); + path = rt->FindPath(vm_intf->peer()); + EXPECT_TRUE(path->path_preference().sequence() == 1); + EXPECT_TRUE(path->path_preference().preference() == PathPreference::HIGH); + EXPECT_TRUE(path->path_preference().ecmp() == false); + EXPECT_TRUE(path->path_preference().wait_for_traffic() == false); + + DelLink("virtual-machine-interface", "vnet1", "security-group", "sg1"); + DelLink("security-group", "sg1", "access-control-list", "acl1"); + DelAcl("acl1"); + DelNode("security-group", "sg1"); + client->WaitForIdle(); +} + + int main(int argc, char *argv[]) { GETUSERARGS(); client = TestInit(init_file, ksync_init); diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index cd30e899f9b..8eac055e474 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -3296,6 +3296,7 @@ void VmInterface::InstanceIpList::Insert(const InstanceIp *rhs) { void VmInterface::InstanceIpList::Update(const InstanceIp *lhs, const InstanceIp *rhs) { lhs->set_del_pending(false); + lhs->ecmp_ = rhs->ecmp_; } void VmInterface::InstanceIpList::Remove(InstanceIpSet::iterator &it) { diff --git a/src/vnsw/agent/oper/vm_interface.h b/src/vnsw/agent/oper/vm_interface.h index 677eb363900..d4e8006ddad 100644 --- a/src/vnsw/agent/oper/vm_interface.h +++ b/src/vnsw/agent/oper/vm_interface.h @@ -336,7 +336,7 @@ class VmInterface : public Interface { } const IpAddress ip_; - bool ecmp_; + mutable bool ecmp_; mutable bool l2_installed_; const Ip4Address gw_ip_; mutable bool old_ecmp_; diff --git a/src/vnsw/agent/pkt/flow_table.cc b/src/vnsw/agent/pkt/flow_table.cc index 515085f8565..d67c0bea4d5 100644 --- a/src/vnsw/agent/pkt/flow_table.cc +++ b/src/vnsw/agent/pkt/flow_table.cc @@ -1325,6 +1325,13 @@ bool FlowEntry::SetRpfNHState(FlowTable *ft, const NextHop *nh) { } } + if (data_.nh_state_ && nh) { + if (data_.nh_state_->nh()->GetType() != NextHop::COMPOSITE && + nh->GetType() == NextHop::COMPOSITE) { + set_flags(FlowEntry::Trap); + } + } + if (data_.nh_state_ != nh_state) { data_.nh_state_ = nh_state; return true;