Skip to content

Commit df27228

Browse files
[NXOS] Diff PIM multicast group bindings individually per RP
Replacing entire StaticRP entries when their multicast group lists change fails on NX-OS with "child (Rn) cannot be added to deleted object Rn=rpgrplist-[...], Commit Failed". Make StaticRPGrp implement Configurable so individual group entries can be added or removed through gNMI. The EnsurePIM reconciliation now diffs RPGrpListList entries per RP: only new groups are created, only removed groups are deleted, and unchanged bindings stay in place. Co-authored-by: i521907 <weneghawi@gmail.com>
1 parent 0d27953 commit df27228

2 files changed

Lines changed: 43 additions & 1 deletion

File tree

internal/provider/cisco/nxos/pim.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ var (
99
_ gnmiext.Configurable = (*PIM)(nil)
1010
_ gnmiext.Configurable = (*PIMDom)(nil)
1111
_ gnmiext.Configurable = (*StaticRPItems)(nil)
12+
_ gnmiext.Configurable = (*StaticRP)(nil)
13+
_ gnmiext.Configurable = (*StaticRPGrp)(nil)
1214
_ gnmiext.Configurable = (*AnycastPeerItems)(nil)
1315
_ gnmiext.Configurable = (*PIMIfItems)(nil)
1416
)
@@ -63,10 +65,18 @@ type StaticRPGrp struct {
6365
Bidir bool `json:"bidir"`
6466
GrpListName string `json:"grpListName"`
6567
Override bool `json:"override"`
68+
69+
// RpAddr is the parent StaticRP address, used to construct the XPath.
70+
// It is not serialized to JSON.
71+
RpAddr string `json:"-"`
6672
}
6773

6874
func (g *StaticRPGrp) Key() string { return g.GrpListName }
6975

76+
func (g *StaticRPGrp) XPath() string {
77+
return "System/pim-items/inst-items/dom-items/Dom-list[name=default]/staticrp-items/rp-items/StaticRP-list[addr=" + g.RpAddr + "]/rpgrplist-items/RPGrpList-list[grpListName=" + g.GrpListName + "]"
78+
}
79+
7080
type AnycastPeerItems struct {
7181
AcastRPPeerList gnmiext.List[AnycastPeerAddr, *AnycastPeerAddr] `json:"AcastRPPeer-list,omitzero"`
7282
}

internal/provider/cisco/nxos/provider.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1705,7 +1705,39 @@ func (p *Provider) EnsurePIM(ctx context.Context, req *provider.EnsurePIMRequest
17051705
del := make([]gnmiext.Configurable, 0, 3)
17061706

17071707
if len(rpItems.StaticRPList) > 0 {
1708-
conf = append(conf, rpItems)
1708+
// Diff group-to-RP bindings individually; replacing entire StaticRP entries fails on NX-OS
1709+
// with "child (Rn) cannot be added to deleted object Rn=rpgrplist-[...], Commit Failed".
1710+
current := new(StaticRPItems)
1711+
if err := p.client.GetConfig(ctx, current); err != nil && !errors.Is(err, gnmiext.ErrNil) {
1712+
return err
1713+
}
1714+
for _, rp := range rpItems.StaticRPList {
1715+
got, ok := current.StaticRPList.Get(rp.Key())
1716+
if !ok {
1717+
// StaticRP does not exist yet — add the entire entry.
1718+
conf = append(conf, rp)
1719+
continue
1720+
}
1721+
for _, grp := range rp.RpgrplistItems.RPGrpListList {
1722+
if gotGrp, ok := got.RpgrplistItems.RPGrpListList.Get(grp.Key()); !ok || !reflect.DeepEqual(gotGrp, grp) {
1723+
g := *grp
1724+
g.RpAddr = rp.Addr
1725+
conf = append(conf, &g)
1726+
}
1727+
}
1728+
for _, grp := range got.RpgrplistItems.RPGrpListList {
1729+
if _, ok := rp.RpgrplistItems.RPGrpListList.Get(grp.Key()); !ok {
1730+
g := *grp
1731+
g.RpAddr = rp.Addr
1732+
del = append(del, &g)
1733+
}
1734+
}
1735+
}
1736+
for _, rp := range current.StaticRPList {
1737+
if _, ok := rpItems.StaticRPList.Get(rp.Key()); !ok {
1738+
del = append(del, rp)
1739+
}
1740+
}
17091741
} else {
17101742
del = append(del, rpItems)
17111743
}

0 commit comments

Comments
 (0)