fix: delete PIM rp-items before multicast group replace#232
fix: delete PIM rp-items before multicast group replace#232
Conversation
Merging this branch will decrease overall coverage
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
There was a problem hiding this comment.
Deleting the whole System/pim-items/inst-items/dom-items/Dom-list[name=default]/staticrp-items/rp-items list container in YANG is way too disruptive!
Assume the case where a user adds an additional rendezvous point, your reflect.DeepEqual would fail and so you would delete the whole list container in one request and recreate it in another request, where each request is a single transaction, so this change is not atomic.
I suggest the following implementation:
- Fetch all rendezvous points from the API
- Loop through all the rendezvous points and check whether they are still in the desired list of rendezvous points
a. If!reflect.DeepEqual(got, want), add asUpdateto the request.
b. If not desired (any longer), add asDeleteto the request.
With this implementation, we would only create an additional rendezvous point in the scenario described above.
This makes use of the fact that the *StaticRP list items, also implement the gnmiext.Configurable interface and as such can be configured with the same client call.
Here is a sample implementation for this, please verify if it works as intended.
diff --git a/internal/provider/cisco/nxos/provider.go b/internal/provider/cisco/nxos/provider.go
index 34243ce7..f6f386aa 100644
--- a/internal/provider/cisco/nxos/provider.go
+++ b/internal/provider/cisco/nxos/provider.go
@@ -1662,18 +1662,17 @@ func (p *Provider) EnsurePIM(ctx context.Context, req *provider.EnsurePIMRequest
del := make([]gnmiext.Configurable, 0, 3)
if len(rpItems.StaticRPList) > 0 {
- // NX-OS fails with "child (Rn) cannot be added to deleted object" when a
- // gNMI Replace tries to update nested rpgrplist-items within a StaticRP
- // in the same transaction (e.g. when multicastGroups change). Work around
- // this by deleting the existing StaticRPItems first when the configuration
- // has changed, so the Replace only needs to add entries.
- currentRPItems := new(StaticRPItems)
- if err := p.client.GetConfig(ctx, currentRPItems); err == nil && !reflect.DeepEqual(rpItems, currentRPItems) {
- if err := p.client.Delete(ctx, new(StaticRPItems)); err != nil {
- return err
+ current := new(StaticRPItems)
+ if err := p.client.GetConfig(ctx, current); err != nil && !errors.Is(err, gnmiext.ErrNil) {
+ return err
+ }
+ for _, rp := range rpItems.StaticRPList {
+ if got, ok := current.StaticRPList.Get(rp.Key()); !ok || !reflect.DeepEqual(got, rp) {
+ conf = append(conf, rp)
+ } else {
+ del = append(del, rp)
}
}
- conf = append(conf, rpItems)
} else {
del = append(del, rpItems)
}
Fix
In
EnsurePIM, before callingUpdate(gNMI Replace), check if the currentStaticRPItemsconfig differs from the desired config. If it does, delete the existing items first in a separate transaction — then the Replace only adds new entries.File:
internal/provider/cisco/nxos/provider.goLive Device Testing
Setup
Reproduce the bug (old behavior)
Enable PIM feature:
Push initial RP with group
225.0.0.0/8:Change group to
226.0.0.0/8— fails with the bug:Verify the fix (delete first, then replace)
Results
225.0.0.0/8226.0.0.0/8(old behavior)rpgrplisterrorrp-items+ replace with226.0.0.0/8(fix)226.0.0.0/8on device