Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const (
niEncapTeVrfD = "ENCAP_TE_VRF_D"
niTeVrf111 = "vrf_t"
niTeVrf222 = "vrf_r"
niRepaired = "vrf_rd"
niDefault = "DEFAULT"
IPBlockEncapA = "101.1.64.1/15" // IPBlockEncapA represents the ipv4 entries in EncapVRFA
IPBlockEncapB = "101.5.64.1/15" // IPBlockEncapB represents the ipv4 entries in EncapVRFB
Expand Down Expand Up @@ -597,7 +598,7 @@ func pushDecapScaleEntries(t *testing.T, args *testArgs, decapEntries []string)
func installDecapEntry(t *testing.T, args *testArgs, nhIndex, nhgIndex uint64, prefix string) {
decapNH := fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(args.dut)).
WithIndex(nhIndex).WithDecapsulateHeader(fluent.IPinIP)
if !deviations.DecapNHWithNextHopNIUnsupported(args.dut) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@snaragund - Why are we removing this deviation statement? Also, I see this deviation is not used by Nokia. This break other vendor tests. Can we please revert this change?

Copy link
Copy Markdown
Contributor Author

@snaragund snaragund Nov 3, 2025

Choose a reason for hiding this comment

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

@ram-mac Deviation statement default value is false hence deviation should have been defined with else condition instead of !deviation. We support decap NH without NI.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ram-mac what are next steps on this PR ?

if deviations.DecapNHWithNextHopNIUnsupported(args.dut) {
decapNH.WithNextHopNetworkInstance(deviations.DefaultNetworkInstance(args.dut))
}
args.client.Modify().AddEntry(t,
Expand Down Expand Up @@ -734,7 +735,7 @@ func configureDUT(t *testing.T, dut *ondatra.DUTDevice) {
dutOCRoot := gnmi.OC()

vrfs := []string{deviations.DefaultNetworkInstance(dut), niDecapTeVrf,
niEncapTeVrfA, niEncapTeVrfB, niEncapTeVrfC, niEncapTeVrfD, niTeVrf111, niTeVrf222}
niEncapTeVrfA, niEncapTeVrfB, niEncapTeVrfC, niEncapTeVrfD, niTeVrf111, niTeVrf222, niRepaired}
createVrf(t, dut, vrfs)

// configure Ethernet interfaces first
Expand Down Expand Up @@ -822,16 +823,19 @@ func configureDUTSubIfs(t *testing.T, dut *ondatra.DUTDevice, dutPort *ondatra.P
gnmi.BatchUpdate(batchConfig, gnmi.OC().Interface(dutPort.Name()).Subinterface(index).Config(), createSubifDUT(t, d, dut, dutPort, index, vlanID, dutIPv4, ipv4PrefixLen))
gnmi.BatchUpdate(batchConfig, gnmi.OC().Interface(dutPort.Name()).Subinterface(index).Config(), createStaticArpEntries(dutPort.Name(), index, ateIPv4, mac))

if deviations.ExplicitInterfaceInDefaultVRF(dut) {
fptest.AssignToNetworkInstance(t, dut, dutPort.Name(), deviations.DefaultNetworkInstance(dut), index)
}
nextHops = append(nextHops, &nextHopIntfRef{
nextHopIPAddress: ateIPv4,
subintfIndex: index,
intfName: dutPort.Name(),
})
}
batchConfig.Set(t, dut)
if deviations.ExplicitInterfaceInDefaultVRF(dut) {
for i := 0; i < *fpargs.DefaultVRFIPv4NHCount; i++ {
index := uint32(i)
fptest.AssignToNetworkInstance(t, dut, dutPort.Name(), deviations.DefaultNetworkInstance(dut), index)
}
}
return nextHops
}

Expand Down Expand Up @@ -971,26 +975,41 @@ func TestGribiEncapDecapScaling(t *testing.T) {
V4ReEncapNHGCount: *fpargs.V4ReEncapNHGCount,
},
)
var maxEntries int = 10000
for _, vrfConfig := range vrfConfigs {
// skip adding unwanted entries
if vrfConfig.Name == "vrf_rd" {
continue
}

entries := append(vrfConfig.NHs, vrfConfig.NHGs...)
entries = append(entries, vrfConfig.V4Entries...)
client.Modify().AddEntry(t, entries...)
if err := awaitTimeout(ctx, client, t, 5*time.Minute); err != nil {
t.Fatalf("Could not program entries, got err: %v", err)
if len(entries) > maxEntries {
index := 0
for idx := 0; idx < len(entries)/maxEntries; idx++ {
client.Modify().AddEntry(t, entries[index:maxEntries+index]...)
if err := awaitTimeout(ctx, client, t, 5*time.Minute); err != nil {
t.Fatalf("Could not program entries, got err: %v", err)
}
index += maxEntries
}
if len(entries)%maxEntries != 0 {
client.Modify().AddEntry(t, entries[index:]...)
if err := awaitTimeout(ctx, client, t, 5*time.Minute); err != nil {
t.Fatalf("Could not program entries, got err: %v", err)
}

}
} else {
client.Modify().AddEntry(t, entries...)
if err := awaitTimeout(ctx, client, t, 5*time.Minute); err != nil {
t.Fatalf("Could not program entries, got err: %v", err)
}
}
t.Logf("Created %d NHs, %d NHGs, %d IPv4Entries in %s VRF", len(vrfConfig.NHs), len(vrfConfig.NHGs), len(vrfConfig.V4Entries), vrfConfig.Name)
}

defaultIpv4Entries := []string{}
for _, v4Entry := range vrfConfigs[1].V4Entries {
ep, _ := v4Entry.EntryProto()
defaultIpv4Entries = append(defaultIpv4Entries, strings.Split(ep.GetIpv4().GetPrefix(), "/")[0])
}

// Inject 5000 IPv4Entry-ies and 5000 IPv6Entry-ies to each of the 4 encap VRFs.
pushEncapEntries(t, defaultIpv4Entries, args)

Expand Down Expand Up @@ -1063,5 +1082,8 @@ func overrideScaleParams(dut *ondatra.DUTDevice) {
encapNhSize = 2
decapIPv4ScaleCount = 400
}
if dut.Vendor() == ondatra.NOKIA {
decapIPv4ScaleCount = 128
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ platform_exceptions: {
no_mix_of_tagged_and_untagged_subinterfaces: true
explicit_interface_in_default_vrf: true
interface_enabled: true
override_default_nh_scale: true
}
}
platform_exceptions: {
Expand Down
23 changes: 10 additions & 13 deletions internal/tescale/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,29 +215,26 @@ func BuildVRFConfig(dut *ondatra.DUTDevice, egressIPs []string, param Param) []*
// * Each NH has one entry for decap and encap
// * All NHG has a backup for decap then goto default VRF.
reEncapNHGRatio := param.V4TunnelCount / param.V4ReEncapNHGCount
nhgID = idPool.NextNHGID()
nhgEntry := fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgDecapToDefault)
for idx, ip := range v4TunnelIPAddrs.AllIPs() {
nhID = idPool.NextNHID()
vrfDefault.NHs = append(vrfDefault.NHs,
fluent.NextHopEntry().WithIndex(nhID).WithDecapsulateHeader(fluent.IPinIP).WithEncapsulateHeader(fluent.IPinIP).
WithNetworkInstance(defaultVRF).WithIPinIP(tunnelSrcIP, v4TunnelIPAddrs.AllIPs()[(idx+1)%len(v4TunnelIPAddrs.AllIPs())]),
)
if idx != 0 && idx%reEncapNHGRatio == 0 {
vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry)
if idx%reEncapNHGRatio == 0 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@snaragund - I know you have optimized the NH scale usage. But i would like to keep this scale on the device for now and not make any changes. Let there be unutilized NH, it is not impacting the functionality anyways.

Copy link
Copy Markdown
Contributor Author

@snaragund snaragund Nov 3, 2025

Choose a reason for hiding this comment

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

@ram-mac Reverted back without optimization, now it will have 29254 NHs, 1543 NHGs. With optimized code it was 9511 NHs, 1287 NHGs.


nhID = idPool.NextNHID()
vrfDefault.NHs = append(vrfDefault.NHs,
fluent.NextHopEntry().WithIndex(nhID).WithDecapsulateHeader(fluent.IPinIP).WithEncapsulateHeader(fluent.IPinIP).
WithNetworkInstance(defaultVRF).WithNextHopNetworkInstance(VRFRD).WithIPinIP(tunnelSrcIP, v4TunnelIPAddrs.AllIPs()[(idx+1)%len(v4TunnelIPAddrs.AllIPs())]),
)
nhgID = idPool.NextNHGID()
nhgEntry = fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgDecapToDefault)
nhgEntry := fluent.NextHopGroupEntry().WithID(nhgID).WithNetworkInstance(defaultVRF).WithBackupNHG(nhgDecapToDefault).AddNextHop(nhID, 1)
vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry)
}
nhgEntry = nhgEntry.AddNextHop(nhID, 1)
vrfRConf.V4Entries = append(vrfRConf.V4Entries,
fluent.IPv4Entry().WithPrefix(ip+"/32").WithNextHopGroup(nhgID).WithNetworkInstance(VRFR).WithNextHopGroupNetworkInstance(defaultVRF),
)
}
vrfDefault.NHGs = append(vrfDefault.NHGs, nhgEntry)

v4VIPAddrs = NewIPPool(iputil.GenerateIPs(V4VIPIPBlock, (param.V4TunnelNHGCount*param.V4TunnelNHGSplitCount)+2))

// VRF_RP
// VRF_RD

// * do the same as Transit VRF
// * but with decap to default NHG
Expand Down
Loading