diff --git a/feature/bgp/otg_tests/bgp_tcp_mss_path_mtu/bgp_tcp_mss_path_mtu_test.go b/feature/bgp/otg_tests/bgp_tcp_mss_path_mtu/bgp_tcp_mss_path_mtu_test.go index 468f7480fdb..58975462e5f 100644 --- a/feature/bgp/otg_tests/bgp_tcp_mss_path_mtu/bgp_tcp_mss_path_mtu_test.go +++ b/feature/bgp/otg_tests/bgp_tcp_mss_path_mtu/bgp_tcp_mss_path_mtu_test.go @@ -118,6 +118,8 @@ func bgpCreateNbr(t *testing.T, dut *ondatra.DUTDevice, authPwd, routerID string global := bgp.GetOrCreateGlobal() global.RouterId = ygot.String(routerID) global.As = ygot.Uint32(localAs) + global.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV4_UNICAST).Enabled = ygot.Bool(true) + global.GetOrCreateAfiSafi(oc.BgpTypes_AFI_SAFI_TYPE_IPV6_UNICAST).Enabled = ygot.Bool(true) pg1 := bgp.GetOrCreatePeerGroup(peerGrpName1) pg1.PeerAs = ygot.Uint32(ateAS1) diff --git a/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go b/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go index deb328c20c9..f1a979f70b4 100644 --- a/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go +++ b/feature/gribi/otg_tests/gribi_scaling/gribi_scaling_test.go @@ -263,7 +263,6 @@ func incrementMAC(mac string, i int) (string, error) { func TestScaling(t *testing.T) { dut := ondatra.DUT(t, "dut") - overrideScaleParams(dut) ate := ondatra.ATE(t, "ate") ctx := context.Background() @@ -399,12 +398,3 @@ func checkTraffic(t *testing.T, ate *ondatra.ATEDevice, top gosnappi.Config) { t.Errorf("FAIL- Got %v%% packet loss for %s ; expected < 1%%", lossPct, "flow") } } - -// overrideScaleParams allows to override the default scale parameters based on the DUT vendor. -func overrideScaleParams(dut *ondatra.DUTDevice) { - if deviations.OverrideDefaultNhScale(dut) { - if dut.Vendor() == ondatra.CISCO { - *fpargs.V4TunnelCount = 3328 - } - } -} diff --git a/feature/gribi/otg_tests/gribi_scaling/metadata.textproto b/feature/gribi/otg_tests/gribi_scaling/metadata.textproto index 393d30f1bd5..b0d851734a9 100644 --- a/feature/gribi/otg_tests/gribi_scaling/metadata.textproto +++ b/feature/gribi/otg_tests/gribi_scaling/metadata.textproto @@ -12,7 +12,6 @@ platform_exceptions: { deviations: { ipv4_missing_enabled: true interface_ref_interface_id_format: true - override_default_nh_scale: true } } platform_exceptions: { diff --git a/feature/gribi/otg_tests/ipv4_entry_test/ipv4_entry_test.go b/feature/gribi/otg_tests/ipv4_entry_test/ipv4_entry_test.go index 7b44b9d500d..2dcf9965d41 100644 --- a/feature/gribi/otg_tests/ipv4_entry_test/ipv4_entry_test.go +++ b/feature/gribi/otg_tests/ipv4_entry_test/ipv4_entry_test.go @@ -117,10 +117,12 @@ func TestMain(m *testing.M) { func staticARPWithMagicUniversalIP(t *testing.T, dut *ondatra.DUTDevice) { t.Helper() + dummyIPCIDR1 := nh1IpAddr + "/32" + dummyIPCIDR2 := nh2IpAddr + "/32" p2 := dut.Port(t, "port2") p3 := dut.Port(t, "port3") s2 := &oc.NetworkInstance_Protocol_Static{ - Prefix: ygot.String(nh1IpAddr + "/32"), + Prefix: ygot.String(dummyIPCIDR1), NextHop: map[string]*oc.NetworkInstance_Protocol_Static_NextHop{ strconv.Itoa(nh1ID): { Index: ygot.String(strconv.Itoa(nh1ID)), @@ -131,7 +133,7 @@ func staticARPWithMagicUniversalIP(t *testing.T, dut *ondatra.DUTDevice) { }, } s3 := &oc.NetworkInstance_Protocol_Static{ - Prefix: ygot.String(nh2IpAddr + "/32"), + Prefix: ygot.String(dummyIPCIDR2), NextHop: map[string]*oc.NetworkInstance_Protocol_Static_NextHop{ strconv.Itoa(nh2ID): { Index: ygot.String(strconv.Itoa(nh2ID)), @@ -141,9 +143,24 @@ func staticARPWithMagicUniversalIP(t *testing.T, dut *ondatra.DUTDevice) { }, }, } + static1 := &oc.NetworkInstance_Protocol{ + Identifier: oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, + Name: ygot.String(deviations.StaticProtocolName(dut)), + Static: map[string]*oc.NetworkInstance_Protocol_Static{ + dummyIPCIDR1: s2, + }, + } + static2 := &oc.NetworkInstance_Protocol{ + Identifier: oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, + Name: ygot.String(deviations.StaticProtocolName(dut)), + Static: map[string]*oc.NetworkInstance_Protocol_Static{ + dummyIPCIDR2: s3, + }, + } + fptest.ConfigureDefaultNetworkInstance(t, dut) sp := gnmi.OC().NetworkInstance(deviations.DefaultNetworkInstance(dut)).Protocol(oc.PolicyTypes_INSTALL_PROTOCOL_TYPE_STATIC, deviations.StaticProtocolName(dut)) - gnmi.Replace(t, dut, sp.Static(nh1IpAddr+"/32").Config(), s2) - gnmi.Replace(t, dut, sp.Static(nh2IpAddr+"/32").Config(), s3) + gnmi.Update(t, dut, sp.Config(), static1) + gnmi.Update(t, dut, sp.Config(), static2) gnmi.Update(t, dut, gnmi.OC().Interface(p2.Name()).Config(), configStaticArp(p2, nh1IpAddr, staticDstMAC)) gnmi.Update(t, dut, gnmi.OC().Interface(p3.Name()).Config(), configStaticArp(p3, nh2IpAddr, staticDstMAC)) } @@ -349,7 +366,7 @@ func TestIPv4Entry(t *testing.T) { if tc.gribiMACOverrideWithStaticARPStaticRoute { staticARPWithMagicUniversalIP(t, dut) } else if tc.gribiMACOverrideWithStaticARP { - //Creating a Static ARP entry for staticDstMAC + // Creating a Static ARP entry for staticDstMAC d := gnmi.OC() p2 := dut.Port(t, "port2") p3 := dut.Port(t, "port3") @@ -359,7 +376,7 @@ func TestIPv4Entry(t *testing.T) { gnmi.Update(t, dut, d.Interface(p3.Name()).Config(), configStaticArp(p3, nh2IpAddr, staticDstMAC)) } if tc.gribiMACOverrideWithStaticARP || tc.gribiMACOverrideWithStaticARPStaticRoute { - //Programming a gRIBI flow with above IP/mac-address as the next-hop entry + // Programming a gRIBI flow with above IP/mac-address as the next-hop entry tc.entries = []fluent.GRIBIEntry{ fluent.NextHopEntry().WithNetworkInstance(deviations.DefaultNetworkInstance(dut)). WithIndex(nh1ID).WithInterfaceRef(dut.Port(t, "port2").Name()).WithIPAddress(nh1IpAddr).WithMacAddress(staticDstMAC), diff --git a/feature/system/logging/otg_tests/remote_syslog/README.md b/feature/system/logging/otg_tests/remote_syslog/README.md new file mode 100644 index 00000000000..1c988aee023 --- /dev/null +++ b/feature/system/logging/otg_tests/remote_syslog/README.md @@ -0,0 +1,86 @@ +# TR-6.1: Remote Syslog feature config + +## Summary + +Verify configuration of remote syslog host (server) in DEFAULT and non-default +VRF. + +## Procedure + +* Connect DUT port-1 with OTG port-1 and DUT port-2 with OTG port-2 +* Configure DUT $VRF-name network-instance and OTG with: + * interface(port-1), interface(port-2) with IPv4 and IPv6 address + * static host routes to syslog server addresses pointing OTG + interface(port-1) IP + * loopback interface with IPv4 and IPv6 address and netmasks of /32, /64 + respectively +* Configure syslog servers DUT + * Configure 1st IPv4 Syslog remote hosts in $VRF-name with: + * facility “local7” and severity “debug” + * (TODO when OC model published) compliance to RFC5424 (structured) + * source address equal to IPv4 address of loopback interface + * Configure 2nd IPv4 Syslog remote hosts in $VRF-name with: + * facility “local7” and severity “critical” + * (TODO when OC model published) compliance to RFC3164 (BSD/original) + * source address equal to IPv4 address of loopback interface + * Configure 3rd IPv6 Syslog remote hosts in $VRF-name with: + * non-standard remote port + * facility “local1” and severity “debug” + * (TODO when OC model published) compliance to RFC5424 (structured) + * source address equal to IPv6 address of loopback interface + * Configure 4th IPv6 Syslog remote hosts in $VRF-name with: + * facility “local7” and severity “critical” + * (TODO when OC model published) compliance to RFC3164 (BSD/original) + * source address equal to IPv6 address of loopback interface +* Test Procedure + * Read configuration of all 4 servers, verify it matches intent + * enable packet capture on OTG port-1 + * disable OTG port-2 so DUT interface(port-2) goes down, which should + generate log + * Observe on OTG capture: + * Syslog packet w/ DstIP of host 1st and 4th and standard dstPort. + * Syslog packet w/ DstIP of host 3rd and non-standard dstPort + * Note: no packet w/ DstIP of 2nd host is expected. + +### Test Case #1 - Default network instance + +``` +* Execute above procedure for $VRF-name = "DEFAULT" (default VRF) +``` + +### Test Case #2 - Non-Default network instance + +``` +* Execute above procedure for $VRF-name = "VRF-foo" +``` + +## OpenConfig Path and RPC Coverage + +```yaml +paths: + ## Config parameter coverage + /system/logging/remote-servers/remote-server/config/host: + /system/logging/remote-servers/remote-server/config/network-instance: + /system/logging/remote-servers/remote-server/config/remote-port: + /system/logging/remote-servers/remote-server/config/source-address: + /system/logging/remote-servers/remote-server/selectors/selector/config/facility: + /system/logging/remote-servers/remote-server/selectors/selector/config/severity: + + ## Telemetry parameter coverage + /system/logging/remote-servers/remote-server/state/host: + /system/logging/remote-servers/remote-server/state/network-instance: + /system/logging/remote-servers/remote-server/state/remote-port: + /system/logging/remote-servers/remote-server/state/source-address: + /system/logging/remote-servers/remote-server/selectors/selector/state/facility: + /system/logging/remote-servers/remote-server/selectors/selector/state/severity: + +rpcs: + gnmi: + gNMI.Get: + gNMI.Subscribe: + gNMI.Set: +``` + +## DUT + +FFF diff --git a/feature/system/logging/otg_tests/remote_syslog/metadata.textproto b/feature/system/logging/otg_tests/remote_syslog/metadata.textproto new file mode 100644 index 00000000000..6331971b622 --- /dev/null +++ b/feature/system/logging/otg_tests/remote_syslog/metadata.textproto @@ -0,0 +1,19 @@ +# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto +# proto-message: Metadata + +uuid: "1f83da73-9db4-43ae-a282-bc309ff64e0e" +plan_id: "TR-6.1" +description: "Remote Syslog feature config" +testbed: TESTBED_DUT_ATE_2LINKS +platform_exceptions: { + platform: { + vendor: ARISTA + } + deviations: { + omit_l2_mtu: true + interface_config_vrf_before_address: true + interface_enabled: true + default_network_instance: "default" + static_protocol_name: "STATIC" + } +} \ No newline at end of file diff --git a/feature/system/logging/otg_tests/remote_syslog/remote_syslog_test.go b/feature/system/logging/otg_tests/remote_syslog/remote_syslog_test.go new file mode 100644 index 00000000000..5ac04c0c873 --- /dev/null +++ b/feature/system/logging/otg_tests/remote_syslog/remote_syslog_test.go @@ -0,0 +1,477 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package remote_syslog_test + +import ( + "fmt" + "net" + "os" + "strconv" + "testing" + "time" + + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" + "github.com/open-traffic-generator/snappi/gosnappi" + "github.com/openconfig/featureprofiles/internal/attrs" + "github.com/openconfig/featureprofiles/internal/cfgplugins" + "github.com/openconfig/featureprofiles/internal/deviations" + "github.com/openconfig/featureprofiles/internal/fptest" + "github.com/openconfig/featureprofiles/internal/otgutils" + "github.com/openconfig/ondatra" + "github.com/openconfig/ondatra/gnmi" + "github.com/openconfig/ondatra/gnmi/oc" + "github.com/openconfig/ondatra/netutil" + "github.com/openconfig/ygot/ygot" +) + +const ( + pLen4 = 30 + pLen6 = 126 + trafficPps = 1000 + totalPackets = 30000 + flowV4 = "flowV4" + flowV6 = "flowV6" + v4Route = "203.0.113.0" + v6Route = "2001:db8:128:128::0" + v4RoutePrefix = uint32(24) + v6RoutePrefix = uint32(64) + lossTolerance = float64(1) +) + +var ( + dutSrc = &attrs.Attributes{ + Desc: "DUT Source", + IPv4: "192.0.2.1", + IPv6: "2001:DB8::192:0:2:1", + IPv4Len: pLen4, + IPv6Len: pLen6, + } + + ateSrc = &attrs.Attributes{ + Name: "port1", + MAC: "02:00:01:01:01:01", + Desc: "ATE Source", + IPv4: "192.0.2.2", + IPv6: "2001:DB8::192:0:2:2", + IPv4Len: pLen4, + IPv6Len: pLen6, + } + + dutDst = &attrs.Attributes{ + Desc: "DUT Destination", + IPv4: "192.0.2.5", + IPv6: "2001:DB8::192:0:2:5", + IPv4Len: pLen4, + IPv6Len: pLen6, + } + + ateDst = &attrs.Attributes{ + Name: "port2", + MAC: "02:00:02:01:01:01", + Desc: "ATE Destination", + IPv4: "192.0.2.6", + IPv6: "2001:DB8::192:0:2:6", + IPv4Len: pLen4, + IPv6Len: pLen6, + } + + dutLoopback = attrs.Attributes{ + Desc: "Loopback ip", + IPv4: "203.0.113.1", + IPv6: "2001:db8::203:0:113:1", + IPv4Len: 32, + IPv6Len: 128, + } + + lb string +) + +func TestMain(m *testing.M) { + fptest.RunTests(m) +} + +func TestRemoteSyslog(t *testing.T) { + dut := ondatra.DUT(t, "dut") + p1 := dut.Port(t, "port1") + p2 := dut.Port(t, "port2") + ate := ondatra.ATE(t, "ate") + lb = netutil.LoopbackInterface(t, dut, 0) + + top := configureATE(t, ate) + createFlow(t, top, true) + createFlow(t, top, false) + enableCapture(t, ate, top) + ate.OTG().PushConfig(t, top) + ate.OTG().StartProtocols(t) + + testCases := []struct { + name string + vrf string + }{ + { + name: "Default VRF", + vrf: deviations.DefaultNetworkInstance(dut), + }, + { + name: "Non-Default VRF", + vrf: "nondefaultvrfx", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.vrf != deviations.DefaultNetworkInstance(dut) { + createAndAddInterfacesToVRF(t, dut, tc.vrf, []string{p1.Name(), p2.Name(), lb}, []uint32{0, 0, 0}) + } + + configureDUT(t, dut, &tc.vrf) + configureDUTLoopback(t, dut) + configureStaticRoute(t, dut, tc.vrf) + configureSyslog(t, dut, tc.vrf) + + otgutils.WaitForARP(t, ate.OTG(), top, "IPv4") + otgutils.WaitForARP(t, ate.OTG(), top, "IPv6") + + cs := startCapture(t, ate, top) + + sleepTime := time.Duration(totalPackets/trafficPps) + 2 + ate.OTG().StartTraffic(t) + flipATEPort(t, dut, ate, top, "port2", false) + time.Sleep(sleepTime * time.Second) + ate.OTG().StopTraffic(t) + + stopCapture(t, ate, cs) + + otgutils.LogFlowMetrics(t, ate.OTG(), top) + otgutils.LogPortMetrics(t, ate.OTG(), top) + + processCapture(t, ate, top) + + t.Cleanup(func() { + gnmi.Delete(t, dut, gnmi.OC().Interface(p1.Name()).Config()) + gnmi.Delete(t, dut, gnmi.OC().Interface(p2.Name()).Config()) + gnmi.Delete(t, dut, gnmi.OC().Interface(lb).Config()) + gnmi.Delete(t, dut, gnmi.OC().NetworkInstance(tc.vrf).Config()) + flipATEPort(t, dut, ate, top, "port2", true) + }) + }) + } +} + +// configureDUT configures port1 and port2 on the DUT +func configureDUT(t *testing.T, dut *ondatra.DUTDevice, vrfName *string) { + dp1 := dut.Port(t, "port1") + dp2 := dut.Port(t, "port2") + + gnmi.Update(t, dut, gnmi.OC().Interface(dp1.Name()).Config(), dutSrc.NewOCInterface(dp1.Name(), dut)) + gnmi.Update(t, dut, gnmi.OC().Interface(dp2.Name()).Config(), dutDst.NewOCInterface(dp2.Name(), dut)) + + if deviations.ExplicitPortSpeed(dut) { + fptest.SetPortSpeed(t, dp1) + fptest.SetPortSpeed(t, dp2) + } + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, dp1.Name(), deviations.DefaultNetworkInstance(dut), 0) + fptest.AssignToNetworkInstance(t, dut, dp2.Name(), deviations.DefaultNetworkInstance(dut), 0) + } + + if vrfName == nil { + fptest.ConfigureDefaultNetworkInstance(t, dut) + } +} + +// configureATE configures port1 and port2 on the ATE +func configureATE(t *testing.T, ate *ondatra.ATEDevice) gosnappi.Config { + top := gosnappi.NewConfig() + ap1 := ate.Port(t, "port1") + ap2 := ate.Port(t, "port2") + + ateSrc.AddToOTG(top, ap1, dutSrc) + ateDst.AddToOTG(top, ap2, dutDst) + + ate.OTG().PushConfig(t, top) + ate.OTG().StartProtocols(t) + + return top +} + +// configureDUTLoopback configures the loopback interface on the DUT +func configureDUTLoopback(t *testing.T, dut *ondatra.DUTDevice) { + t.Helper() + // lb = netutil.LoopbackInterface(t, dut, 0) + lo0 := gnmi.OC().Interface(lb).Subinterface(0) + ipv4Addrs := gnmi.LookupAll(t, dut, lo0.Ipv4().AddressAny().State()) + ipv6Addrs := gnmi.LookupAll(t, dut, lo0.Ipv6().AddressAny().State()) + foundV4 := false + for _, ip := range ipv4Addrs { + if v, ok := ip.Val(); ok { + foundV4 = true + dutLoopback.IPv4 = v.GetIp() + break + } + } + foundV6 := false + for _, ip := range ipv6Addrs { + if v, ok := ip.Val(); ok { + foundV6 = true + dutLoopback.IPv6 = v.GetIp() + break + } + } + if !foundV4 || !foundV6 { + lo1 := dutLoopback.NewOCInterface(lb, dut) + lo1.Type = oc.IETFInterfaces_InterfaceType_softwareLoopback + gnmi.Update(t, dut, gnmi.OC().Interface(lb).Config(), lo1) + } + + if deviations.ExplicitInterfaceInDefaultVRF(dut) { + fptest.AssignToNetworkInstance(t, dut, lb, deviations.DefaultNetworkInstance(dut), 0) + } +} + +func createAndAddInterfacesToVRF(t *testing.T, dut *ondatra.DUTDevice, vrfname string, intfNames []string, unit []uint32) { + root := &oc.Root{} + batchConfig := &gnmi.SetBatch{} + for index, intfName := range intfNames { + i := root.GetOrCreateInterface(intfName) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + i.Description = ygot.String(fmt.Sprintf("Port %s", strconv.Itoa(index+1))) + if intfName == netutil.LoopbackInterface(t, dut, 0) { + i.Type = oc.IETFInterfaces_InterfaceType_softwareLoopback + i.Description = ygot.String(fmt.Sprintf("Port %s", intfName)) + } + si := i.GetOrCreateSubinterface(unit[index]) + si.Enabled = ygot.Bool(true) + gnmi.BatchUpdate(batchConfig, gnmi.OC().Interface(intfName).Config(), i) + } + + mgmtNI := root.GetOrCreateNetworkInstance(vrfname) + mgmtNI.Type = oc.NetworkInstanceTypes_NETWORK_INSTANCE_TYPE_L3VRF + for index, intfName := range intfNames { + vi := mgmtNI.GetOrCreateInterface(intfName) + vi.Interface = ygot.String(intfName) + vi.Subinterface = ygot.Uint32(unit[index]) + } + gnmi.BatchReplace(batchConfig, gnmi.OC().NetworkInstance(vrfname).Config(), mgmtNI) + batchConfig.Set(t, dut) + t.Logf("Added interface %v to VRF %s", intfNames, vrfname) +} + +func configureStaticRoute(t *testing.T, dut *ondatra.DUTDevice, ni string) { + b := &gnmi.SetBatch{} + sV4 := &cfgplugins.StaticRouteCfg{ + NetworkInstance: ni, + Prefix: v4Route + "/30", + NextHops: map[string]oc.NetworkInstance_Protocol_Static_NextHop_NextHop_Union{ + "0": oc.UnionString(ateSrc.IPv4), + }, + } + if _, err := cfgplugins.NewStaticRouteCfg(b, sV4, dut); err != nil { + t.Fatalf("Failed to configure IPv4 static route: %v", err) + } + sV6 := &cfgplugins.StaticRouteCfg{ + NetworkInstance: ni, + Prefix: v6Route + "/126", + NextHops: map[string]oc.NetworkInstance_Protocol_Static_NextHop_NextHop_Union{ + "0": oc.UnionString(ateSrc.IPv6), + }, + } + if _, err := cfgplugins.NewStaticRouteCfg(b, sV6, dut); err != nil { + t.Fatalf("Failed to configure IPv6 static route: %v", err) + } + b.Set(t, dut) +} + +func configureSyslog(t *testing.T, dut *ondatra.DUTDevice, ni string) { + root := &oc.Root{} + logging := root.GetOrCreateSystem().GetOrCreateLogging() + + remoteServer1 := logging.GetOrCreateRemoteServer("203.0.113.1") + remoteServer1.SetNetworkInstance(ni) + remoteServer1.SetSourceAddress(dutLoopback.IPv4) + remoteServer1.GetOrCreateSelector( + oc.SystemLogging_SYSLOG_FACILITY_LOCAL7, + oc.SystemLogging_SyslogSeverity_DEBUG, + ) + + remoteServer2 := logging.GetOrCreateRemoteServer("203.0.113.2") + remoteServer2.SetNetworkInstance(ni) + remoteServer2.SetSourceAddress(dutLoopback.IPv4) + remoteServer2.GetOrCreateSelector( + oc.SystemLogging_SYSLOG_FACILITY_LOCAL7, + oc.SystemLogging_SyslogSeverity_CRITICAL, + ) + + remoteServer3 := logging.GetOrCreateRemoteServer("2001:db8:128:128::1") + remoteServer3.SetNetworkInstance(ni) + remoteServer3.SetRemotePort(5140) + remoteServer3.SetSourceAddress(dutLoopback.IPv6) + remoteServer3.GetOrCreateSelector( + oc.SystemLogging_SYSLOG_FACILITY_LOCAL1, + oc.SystemLogging_SyslogSeverity_DEBUG, + ) + + remoteServer4 := logging.GetOrCreateRemoteServer("2001:db8:128:128::2") + remoteServer4.SetNetworkInstance(ni) + remoteServer4.SetSourceAddress(dutLoopback.IPv6) + remoteServer4.GetOrCreateSelector( + oc.SystemLogging_SYSLOG_FACILITY_LOCAL7, + oc.SystemLogging_SyslogSeverity_CRITICAL, + ) + + gnmi.Replace(t, dut, gnmi.OC().System().Logging().Config(), logging) +} + +// createFlow creates a traffic flow with fixed number of packets +func createFlow(t *testing.T, top gosnappi.Config, isV4 bool) { + flowName := flowV4 + if !isV4 { + flowName = flowV6 + } + + flow := top.Flows().Add().SetName(flowName) + flow.Metrics().SetEnable(true) + if isV4 { + flow.TxRx().Device(). + SetTxNames([]string{ateSrc.Name + ".IPv4"}). + SetRxNames([]string{ateDst.Name + ".IPv4"}) + } else { + flow.TxRx().Device(). + SetTxNames([]string{ateSrc.Name + ".IPv6"}). + SetRxNames([]string{ateDst.Name + ".IPv6"}) + } + + flow.Duration().FixedPackets().SetPackets(totalPackets) + flow.Size().SetFixed(1500) + flow.Rate().SetPps(trafficPps) + + ethHdr := flow.Packet().Add().Ethernet() + ethHdr.Src().SetValue(ateSrc.MAC) + + if isV4 { + ipv4Hdr := flow.Packet().Add().Ipv4() + ipv4Hdr.Src().SetValue(ateSrc.IPv4) + ipv4Hdr.Dst().SetValue(ateDst.IPv4) + } else { + ipv6Hdr := flow.Packet().Add().Ipv6() + ipv6Hdr.Src().SetValue(ateSrc.IPv6) + ipv6Hdr.Dst().SetValue(ateDst.IPv6) + } +} + +func flipATEPort(t *testing.T, dut *ondatra.DUTDevice, ate *ondatra.ATEDevice, top gosnappi.Config, port string, enable bool) { + expStatus := oc.Interface_OperStatus_DOWN + if enable { + expStatus = oc.Interface_OperStatus_UP + } + if deviations.ATEPortLinkStateOperationsUnsupported(ate) { + dutP := dut.Port(t, port) + dc := gnmi.OC() + i := &oc.Interface{} + i.Enabled = ygot.Bool(enable) + i.Name = ygot.String(dutP.Name()) + i.Type = oc.IETFInterfaces_InterfaceType_ethernetCsmacd + gnmi.Update(t, dut, dc.Interface(dutP.Name()).Config(), i) + } else { + portStateAction := gosnappi.NewControlState() + if enable { + portStateAction.Port().Link().SetPortNames([]string{port}).SetState(gosnappi.StatePortLinkState.UP) + } else { + portStateAction.Port().Link().SetPortNames([]string{port}).SetState(gosnappi.StatePortLinkState.DOWN) + } + ate.OTG().SetControlState(t, portStateAction) + } + gnmi.Await(t, dut, gnmi.OC().Interface(dut.Port(t, port).Name()).OperStatus().State(), 2*time.Minute, expStatus) +} + +func enableCapture(t *testing.T, ate *ondatra.ATEDevice, config gosnappi.Config) { + t.Helper() + + config.Captures().Clear() + + // enable packet capture on this port + config.Captures().Add().SetName("sFlowpacketCapture"). + SetPortNames([]string{config.Ports().Items()[0].Name()}). + SetFormat(gosnappi.CaptureFormat.PCAP) + + pb, _ := config.Marshal().ToProto() + t.Log(pb.GetCaptures()) +} + +func startCapture(t *testing.T, ate *ondatra.ATEDevice, config gosnappi.Config) gosnappi.ControlState { + t.Helper() + + cs := gosnappi.NewControlState() + cs.Port().Capture().SetState(gosnappi.StatePortCaptureState.START) + ate.OTG().SetControlState(t, cs) + + return cs +} + +func stopCapture(t *testing.T, ate *ondatra.ATEDevice, cs gosnappi.ControlState) { + t.Helper() + cs.Port().Capture().SetState(gosnappi.StatePortCaptureState.STOP) + ate.OTG().SetControlState(t, cs) +} + +func processCapture(t *testing.T, ate *ondatra.ATEDevice, config gosnappi.Config) { + bytes := ate.OTG().GetCapture(t, gosnappi.NewCaptureRequest().SetPortName(config.Ports().Items()[0].Name())) + time.Sleep(30 * time.Second) + pcapFile, err := os.CreateTemp("", "pcap") + if err != nil { + t.Errorf("ERROR: Could not create temporary pcap file: %v\n", err) + } + if _, err := pcapFile.Write(bytes); err != nil { + t.Errorf("ERROR: Could not write bytes to pcap file: %v\n", err) + } + pcapFile.Close() + validatePackets(t, pcapFile.Name()) +} + +func validatePackets(t *testing.T, filename string) { + handle, err := pcap.OpenOffline(filename) + if err != nil { + t.Fatal(err) + } + defer handle.Close() + + loopbackV4 := net.ParseIP(dutLoopback.IPv4) + loopbackV6 := net.ParseIP(dutLoopback.IPv6) + packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) + + foundV4 := false + foundV6 := false + for packet := range packetSource.Packets() { + if ipLayer := packet.Layer(layers.LayerTypeIPv4); ipLayer != nil { + ipv4, _ := ipLayer.(*layers.IPv4) + if ipv4.SrcIP.Equal(loopbackV4) { + foundV4 = true + t.Logf("tos %d, payload %d, content %d, length %d", ipv4.TOS, len(ipv4.Payload), len(ipv4.Contents), ipv4.Length) + } + } else if ipLayer := packet.Layer(layers.LayerTypeIPv6); ipLayer != nil { + ipv6, _ := ipLayer.(*layers.IPv6) + if ipv6.SrcIP.Equal(loopbackV6) { + foundV6 = true + t.Logf("tos %d, payload %d, content %d, length %d", ipv6.TrafficClass, len(ipv6.Payload), len(ipv6.Contents), ipv6.Length) + } + } + + } + + if !foundV4 { + t.Errorf("sflow packets not found: v4 %v, v6 %v", foundV4, foundV6) + } +} diff --git a/feature/system/logging/remote_syslog/feature.textproto b/feature/system/logging/remote_syslog/feature.textproto deleted file mode 100644 index 6c14fbb34ba..00000000000 --- a/feature/system/logging/remote_syslog/feature.textproto +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2022 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# proto-file: github.com/openconfig/featureprofiles/proto/feature.proto -# proto-message: FeatureProfile - -id { - name: "system_logging_remote_syslog" - version: 1 -} - -# remote syslog -config_path { - path: "/system/logging/remote-servers/remote-server/config/host" -} -config_path { - path: "/system/logging/remote-servers/remote-server/config/network-instance" -} -config_path { - path: "/system/logging/remote-servers/remote-server/config/remote-port" -} -config_path { - path: "/system/logging/remote-servers/remote-server/config/source-address" -} -config_path { - path: "/system/logging/remote-servers/remote-server/selectors/selector/config/facility" -} -config_path { - path: "/system/logging/remote-servers/remote-server/selectors/selector/config/severity" -} -telemetry_path { - path: "/system/logging/remote-servers/remote-server/state/host" -} -telemetry_path { - path: "/system/logging/remote-servers/remote-server/state/network-instance" -} -telemetry_path { - path: "/system/logging/remote-servers/remote-server/state/remote-port" -} -telemetry_path { - path: "/system/logging/remote-servers/remote-server/state/source-address" -} -telemetry_path { - path: "/system/logging/remote-servers/remote-server/selectors/selector/state/facility" -} -telemetry_path { - path: "/system/logging/remote-servers/remote-server/selectors/selector/state/severity" -} diff --git a/feature/system/logging/remote_syslog/otg_tests/README.md b/feature/system/logging/remote_syslog/otg_tests/README.md deleted file mode 100644 index c0c5930b0e9..00000000000 --- a/feature/system/logging/remote_syslog/otg_tests/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# TR-6.1: Remote Syslog feature config - -## Summary - -Verify configuration of remote syslog host (server) in DEFAULT and non-default VRF. - -## Procedure -* connect DUT port-1 with OTG port-1 and DUT port-2 with OTG port-2 -* Configure DUT $VRF-name network-instance and OTG with: - * interface(port-1), interface(port-2) with IPv4 and IPv6 address - * static host routes to syslog servers's addresses pointing OTG interface(port-1) IP - * loopback interface with IPv4 and IPv6 address and netmasks of /32, /64 respectively -* Configure syslog servers DUT - * Configure 1st IPv4 Syslog remote hosts in $VRF-name with: - * facility “local7” and severity “debug” - * (TODO when OC model published) complince to RFC5424 (structured) - * source address equall to IPv4 address of loopback interface - * Configure 2nd IPv4 Syslog remote hosts in $VRF-name with: - * facility “local7” and severity “critical” - * (TODO when OC model published) complince to RFC3164 (BSD/original) - * source address equall to IPv4 address of loopback interface - * Configure 3nd IPv6 Syslog remote hosts in $VRF-name with: - * non-standard remote port - * facility “local1” and severity “debug” - * (TODO when OC model published) complince to RFC5424 (structured) - * source address equall to IPv6 address of loopback interface - * Configure 4nd IPv6 Syslog remote hosts in $VRF-name with: - * facility “local7” and severity “critical” - * (TODO when OC model published) complince to RFC3164 (BSD/original) - * source address equall to IPv6 address of loopback interface -* Test Procedure - * Read configuration of all 4 servers, verify it matches intent - * enable packet capture on OTG port-1 - * disable OTG port-2 so DUT interface(port-2) goes down, what should generate log - * Observe on OTG capture: - * Syslog packet w/ DstIP of host 1st and 4th and standard dstPort. - * Syslog packet w/ DstIP of host 3rd and non-standard dstPort - * Note: no packet w/ DstIP of 2nd host is expected. - -### Test Case #1 - Default network instance - * Execute above procedure for $VRF-name = "DEFAULT" (default VRF) - -### Test Case #2 - Non-Default network instance - * Execute above procedure for $VRF-name = "VRF-foo" - - -## Config parameter coverage -* /system/logging/remote-servers/remote-server/config/host -* /system/logging/remote-servers/remote-server/config/network-instance -* /system/logging/remote-servers/remote-server/config/remote-port -* /system/logging/remote-servers/remote-server/config/source-address -* /system/logging/remote-servers/remote-server/selectors/selector/config/facility -* /system/logging/remote-servers/remote-server/selectors/selector/config/severity - -## Telemetry parameter coverage -* /system/logging/remote-servers/remote-server/state/host -* /system/logging/remote-servers/remote-server/state/network-instance -* /system/logging/remote-servers/remote-server/state/remote-port -* /system/logging/remote-servers/remote-server/state/source-address -* /system/logging/remote-servers/remote-server/selectors/selector/state/facility -* /system/logging/remote-servers/remote-server/selectors/selector/state/severity - - -## DUT -FFF - diff --git a/feature/system/logging/remote_syslog/otg_tests/metadata.textproto b/feature/system/logging/remote_syslog/otg_tests/metadata.textproto deleted file mode 100644 index 001be11ca91..00000000000 --- a/feature/system/logging/remote_syslog/otg_tests/metadata.textproto +++ /dev/null @@ -1,7 +0,0 @@ -# proto-file: github.com/openconfig/featureprofiles/proto/metadata.proto -# proto-message: Metadata - -uuid: "1f83da73-9db4-43ae-a282-bc309ff64e0e" -plan_id: "TR-6.1" -description: "Remote Syslog feature config" -testbed: TESTBED_DUT_ATE_2LINKS diff --git a/tools/ci-trigger/Dockerfile b/tools/ci-trigger/Dockerfile index 9ef4a65f0c2..58d6abdd93e 100644 --- a/tools/ci-trigger/Dockerfile +++ b/tools/ci-trigger/Dockerfile @@ -1,8 +1,8 @@ -FROM golang:1.21 as builder +FROM golang:1 as builder WORKDIR /app COPY . /app/ RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -v -o server github.com/openconfig/featureprofiles/tools/ci-trigger -FROM golang:1.21-alpine +FROM golang:1-alpine COPY --from=builder /app/server /server ENTRYPOINT ["/server"] CMD ["-alsologtostderr"] diff --git a/tools/ci-trigger/cloudbuild.yaml b/tools/ci-trigger/cloudbuild.yaml index 41819d1663c..ac742d7d964 100644 --- a/tools/ci-trigger/cloudbuild.yaml +++ b/tools/ci-trigger/cloudbuild.yaml @@ -1,5 +1,5 @@ steps: - - name: golang:1.21 + - name: golang:1 entrypoint: /bin/bash args: [ '-c', 'go test -timeout 5m -v github.com/openconfig/featureprofiles/tools/ci-trigger/...'] - name: 'gcr.io/cloud-builders/docker'