Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fdborch]: Flush fdb entries on port link down (Resolves #1063, #1294, resolves Azure/sonic-buildimage#4184) #1295

Closed
wants to merge 1 commit into from

Conversation

MikeHcChen
Copy link

@MikeHcChen MikeHcChen commented May 15, 2020

What I did

  1. Add a method to inform fdborch to flush FDB while port operation status changed.
  2. Implement codes for processing events of the flushed FDB on specified port or vlan notifications of SAI

Why I did it
Fix issue: [FDB] Doesn't flush fdb entries on port link down #1294

How I verified it
Please refer test steps in [FDB] Doesn't flush fdb entries on port link down #1294

Test on broadcom platform 'x86_64-delta_ag9032v1-r0 with SONiC Software Version: 201911 branch commit 2218ed4 on May 1, 2020.

Details if related

Add a method to inform fdborch to flush FDB while port operation status changed.

Implement processing events of the flushed FDB on specified port or vlan notifications of SAI
@msftclas
Copy link

msftclas commented May 15, 2020

CLA assistant check
All CLA requirements met.

@MikeHcChen MikeHcChen changed the title [fdborch]: Flush fdb entries on port link down (#1294) [fdborch]: Flush fdb entries on port link down (Fix issue #1294) May 15, 2020
@MikeHcChen MikeHcChen changed the title [fdborch]: Flush fdb entries on port link down (Fix issue #1294) [fdborch]: Flush fdb entries on port link down (Fixes #1294) May 15, 2020
@MikeHcChen MikeHcChen changed the title [fdborch]: Flush fdb entries on port link down (Fixes #1294) [fdborch]: Flush fdb entries on port link down (Resolves #1294, resolves Azure/sonic-buildimage#4184) May 15, 2020
@prsunny
Copy link
Collaborator

prsunny commented May 18, 2020

There is a similar PR that handles this use-case differently - #909. It could be incomplete based on the changes you provided in this PR. One question is when you do "flush" do you also get FDB delete notifications back from SAI for each of the entry that's removed?

@MikeHcChen
Copy link
Author

MikeHcChen commented May 20, 2020

There is a similar PR that handles this use-case differently - #909. It could be incomplete based on the changes you provided in this PR. One question is when you do "flush" do you also get FDB delete notifications back from SAI for each of the entry that's removed?

Thanks for your comment.
This PR is focused on flushing FDB after normal port's removing or shutdown, and it is not complicated as PR#909 which contains LAG concerns.

If we do 'flush'on a port, the ASIC will finally notify SONiC with sai_fdb_event_t
event type 'SAI_FDB_EVENT_AGED' or 'SAI_FDB_EVENT_FLUSHED' depending on chip venders' SAI implementation .
The flow chart will be like: https://github.com/Azure/SONiC/blob/master/doc/layer2-forwarding-enhancements/images/portDownFlush.jpg

For case SAI_FDB_EVENT_AGED, original (FdbOrch::update() in fdborch.cpp) codes can handle well.
For case SAI_FDB_EVENT_FLUSHED, I added codes to handle
the notification of flushed a port in case SAI_FDB_EVENT_FLUSHED of FdbOrch::update() in fdborch.cpp.

@MikeHcChen MikeHcChen changed the title [fdborch]: Flush fdb entries on port link down (Resolves #1294, resolves Azure/sonic-buildimage#4184) [fdborch]: Flush fdb entries on port link down (Resolves #1063, #1294, resolves Azure/sonic-buildimage#4184) May 28, 2020
@@ -259,6 +337,40 @@ bool FdbOrch::getPort(const MacAddress& mac, uint16_t vlan, Port& port)
return true;
}

bool FdbOrch::ifChangeInformFdb(Port &port, bool if_up)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the name looks better as flushFdbEntries

@prsunny
Copy link
Collaborator

prsunny commented May 28, 2020

Looks like there is also another PR that handles this - https://github.com/Azure/sonic-swss/pull/1242/files. @vasant17 , can you review this PR?

@@ -186,17 +186,95 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj
}
else if (bridge_port_id && entry->bv_id == SAI_NULL_OBJECT_ID)
{
/*this is a placeholder for flush port fdb case, not supported yet.*/
SWSS_LOG_ERROR("FdbOrch notification: not supported flush port fdb action, port_id = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ".", bridge_port_id, entry->bv_id);
if (!m_portsOrch->getPortByBridgePortId(bridge_port_id, update.port))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we call SAI flush API, with bridge_port_id, we get SAI_FDB_EVENT_AGED event but NOT SAI_FDB_EVENT_FLUSHED. I did verify it by looking at logs. So, here is my understanding

  1. If we call SAI flush API with bvid and bridge_port_id both set to SAI_NULL_OBJECT_ID, we get the notification SAI_FDB_EVENT_FLUSHED. So the new code you added wont be exericised as it will enter the first if case
if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id == SAI_NULL_OBJECT_ID)
  1. When we call SAI FDB flush API with either bvid or bridge_port_id or both valid, we would end up receiving SAI_FDB_EVENT_AGED. Hence. Again the new code you added here wont be exercised.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we call SAI flush API, with bridge_port_id, we get SAI_FDB_EVENT_AGED event but NOT SAI_FDB_EVENT_FLUSHED. I did verify it by looking at logs. So, here is my understanding

  1. If we call SAI flush API with bvid and bridge_port_id both set to SAI_NULL_OBJECT_ID, we get the notification SAI_FDB_EVENT_FLUSHED. So the new code you added wont be exericised as it will enter the first if case
if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id == SAI_NULL_OBJECT_ID)
  1. When we call SAI FDB flush API with either bvid or bridge_port_id or both valid, we would end up receiving SAI_FDB_EVENT_AGED. Hence. Again the new code you added here wont be exercised.

Sorry, I take back my comment on receiving SAI_FDB_EVENT_AGED instead of instead of SAI_FDB_EVENT_FLUSHED. My observation was on one platform. But it was NOT the same on VS container

@@ -3830,6 +3832,11 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status)
{
SWSS_LOG_WARN("Inform nexthop operation failed for interface %s", port.m_alias.c_str());
}

if (!gFdbOrch->ifChangeInformFdb(port, isUp))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we are just following the way ifChangeInformNextHop is done and introducing ifChangeInformFdb. And I was coding up the same solution yesterday and thought of doing it a different way. That is, today at most places if NOT all, we interact between modules using observer pattern. For example, when port gets created or deleted, portsOrch notifies all the observers. I think we should leverage that or follow the pattern to notify observers about port state change. That way we dont have introduce a new function for every module that wants to port status change. With my new code change, we should be able to delete ifChangeInformNextHop and let neighborOrch handle port status change notification. Please refer PR #1242. I will push the code in couple of hours

@@ -9,6 +9,7 @@ struct FdbEntry
{
MacAddress mac;
sai_object_id_t bv_id;
std::string port_name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked this. This was much needed!

/* Update entry's port name if needed */
if (entry.port_name.empty())
{
entry.port_name = port_name;
Copy link
Contributor

@vasant17 vasant17 May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case, the entry is created without port name?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We add an entry to m_entries in two places. One is storeFdbEntryState() and other is addFdbEntry(), Could you please make sure in both places we set port_name in entry before adding to m_entries?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this part of codes is now redundant in my PR.
I write this part of codes just for maximized backward compatibility when someone adds/tests their own codes which call addFdbEntry() with parameter of FdbEntry& entry in old fashion contents (only mac and bv_id).

@@ -429,7 +543,7 @@ void FdbOrch::updateVlanMember(const VlanMemberUpdate& update)
auto fdb_list = std::move(saved_fdb_entries[port_name]);
if(!fdb_list.empty())
{
for (const auto& fdb: fdb_list)
for (auto& fdb: fdb_list)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid making the mutable.

@@ -438,7 +552,7 @@ void FdbOrch::updateVlanMember(const VlanMemberUpdate& update)
}
}

bool FdbOrch::addFdbEntry(const FdbEntry& entry, const string& port_name, const string& type)
bool FdbOrch::addFdbEntry(FdbEntry& entry, const string& port_name, const string& type)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I think, we shouldn't make entry mutable. Here is my suggestion:

Change prototype of addFdbEntry() by removing port from parameter list, as it's already part of FDB entry structure. As far as I remember addFdbEntry is called from only two places and you can populate entry.port_name in both places. In fact you don't have to do anything when it's called from updateVlanMember().

Also note that you have to make some changes in storeFdbStateEntry().
It is called from only update() method in three cases. LEARN, AGED/MOVE, FLUSH.

LEARN is the only case where storeFdbStateEntry() ends up adding the entry to m_entries/saved_fdb_entries. So, populate entry.port_name in LEARN case before calling storeFdbStateEntry().

And in the other two cases(AGED/MOVE, FLUSH), anyways we are going to remove the entry from m_entries, hence no need to populate entry.port_name. Also note that you can go ahead and cleanup(delete) few lines of port related code in storeFdbStateEntry().

@prsunny
Copy link
Collaborator

prsunny commented Jul 8, 2020

@MikeHcChen , PR #1242 is merged which handles the same functionality. Can you close this PR?

@MikeHcChen
Copy link
Author

@MikeHcChen , PR #1242 is merged which handles the same functionality. Can you close this PR?

OK! Thanks.

@MikeHcChen MikeHcChen closed this Jul 9, 2020
EdenGri pushed a commit to EdenGri/sonic-swss that referenced this pull request Feb 28, 2022
…#1295)

* Fix fast-reboot when NDP present
The IPv6 address delimiter ':' caused an exception

Signed-off-by: Shlomi Bitton <shlomibi@nvidia.com>

* Add a comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants