Skip to content

Commit

Permalink
[TEST]: Improvement: Switches: New interaction approach: Phase3
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuliia Miroshnychenko committed Feb 7, 2025
1 parent 9bf1a79 commit 44e778c
Show file tree
Hide file tree
Showing 13 changed files with 807 additions and 966 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import org.openkilda.northbound.dto.v2.switches.LagPortRequest
import org.openkilda.northbound.dto.v2.switches.LagPortResponse
import org.openkilda.northbound.dto.v2.switches.MeterInfoDtoV2
import org.openkilda.northbound.dto.v2.switches.PortPropertiesDto
import org.openkilda.northbound.dto.v2.switches.SwitchDtoV2
import org.openkilda.northbound.dto.v2.switches.SwitchFlowsPerPortResponse
import org.openkilda.northbound.dto.v2.switches.SwitchLocationDtoV2
import org.openkilda.northbound.dto.v2.switches.SwitchPatchDto
Expand Down Expand Up @@ -56,12 +55,9 @@ import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Scope
import org.springframework.stereotype.Component

import java.math.RoundingMode

import static groovyx.gpars.GParsPool.withPool
import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.Matchers.hasItem
import static org.hamcrest.Matchers.notNullValue
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.DELETE_LAG_LOGICAL_PORT
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.DELETE_MIRROR
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.OTHER
Expand Down Expand Up @@ -165,16 +161,6 @@ class SwitchHelper {
"${sw.nbFormat().hardware} ${sw.nbFormat().software}"
}

@Memoized
static String getHwSwString(SwitchDto sw) {
"${sw.hardware} ${sw.software}"
}

@Memoized
static String getHwSwString(SwitchDtoV2 sw) {
"${sw.hardware} ${sw.software}"
}

static List<TraffGen> getTraffGens(Switch sw) {
topology.get().activeTraffGens.findAll { it.switchConnected.dpId == sw.dpId }
}
Expand Down Expand Up @@ -414,39 +400,6 @@ class SwitchHelper {
return northboundV2.get().getSwitchFlows(switchId, []).flowsByPort.keySet().asList()
}

/**
* This method calculates expected burst for different types of switches. The common burst equals to
* `rate * burstCoefficient`. There are couple exceptions though:<br>
* <b>Noviflow</b>: Does not use our common burst coefficient and overrides it with its own coefficient (see static
* variables at the top of the class).<br>
* <b>Centec</b>: Follows our burst coefficient policy, except for restrictions for the minimum and maximum burst.
* In cases when calculated burst is higher or lower of the Centec max/min - the max/min burst value will be used
* instead.
*
* @param sw switchId where burst is being calculated. Needed to get the switch manufacturer and apply special
* calculations if required
* @param rate meter rate which is used to calculate burst
* @return the expected burst value for given switch and rate
*/
def getExpectedBurst(SwitchId sw, long rate) {
def descr = getDescription(sw).toLowerCase()
def hardware = northbound.get().getSwitch(sw).hardware
if (descr.contains("noviflow") || hardware =~ "WB5164") {
return (rate * NOVIFLOW_BURST_COEFFICIENT - 1).setScale(0, RoundingMode.CEILING)
} else if (descr.contains("centec")) {
def burst = (rate * burstCoefficient).toBigDecimal().setScale(0, RoundingMode.FLOOR)
if (burst <= CENTEC_MIN_BURST) {
return CENTEC_MIN_BURST
} else if (burst > CENTEC_MIN_BURST && burst <= CENTEC_MAX_BURST) {
return burst
} else {
return CENTEC_MAX_BURST
}
} else {
return (rate * burstCoefficient).round(0)
}
}

/**
* Verifies that specified meter sections in the validation response are empty.
* NOTE: will filter out default meters for 'proper' section, so that switch without flow meters, but only with
Expand All @@ -469,24 +422,6 @@ class SwitchHelper {
assertions.verify()
}

static void verifyMeterSectionsAreEmpty(SwitchValidationV2ExtendedResult switchValidateInfo,
List<String> sections = ["missing", "misconfigured", "proper", "excess"]) {
def assertions = new SoftAssertions()
if (switchValidateInfo.meters) {
sections.each { section ->
if (section == "proper") {
assertions.checkSucceeds {
assert switchValidateInfo.meters.proper.findAll { !it.defaultMeter }.empty
}
} else {
assertions.checkSucceeds { assert switchValidateInfo.meters."$section".empty }
}
}
}
assertions.verify()
}


/**
* Verifies that specified rule sections in the validation response are empty.
* NOTE: will filter out default rules, except default flow rules(multiTable flow)
Expand All @@ -511,54 +446,6 @@ class SwitchHelper {
assertions.verify()
}

static void verifyRuleSectionsAreEmpty(SwitchValidationV2ExtendedResult switchValidateInfo,
List<String> sections = ["missing", "proper", "excess", "misconfigured"]) {
def assertions = new SoftAssertions()
sections.each { String section ->
if (section == "proper") {
assertions.checkSucceeds {
assert switchValidateInfo.rules.proper.findAll {
def cookie = new Cookie(it.cookie)
!cookie.serviceFlag && cookie.type != CookieType.SHARED_OF_FLOW
}.empty
}
} else {
assertions.checkSucceeds { assert switchValidateInfo.rules."$section".empty }
}
}
assertions.verify()
}

/**
* Verifies that specified hexRule sections in the validation response are empty.
* NOTE: will filter out default rules, except default flow rules(multiTable flow)
* Default flow rules for the system looks like as a simple default rule.
* Based on that you have to use extra filter to detect these rules in
* missingHex/excessHex/misconfiguredHex sections.
*/
static void verifyHexRuleSectionsAreEmpty(SwitchValidationExtendedResult switchValidateInfo,
List<String> sections = ["properHex", "excessHex", "missingHex",
"misconfiguredHex"]) {
def assertions = new SoftAssertions()
sections.each { String section ->
if (section == "properHex") {
def defaultCookies = switchValidateInfo.rules.proper.findAll {
def cookie = new Cookie(it)
cookie.serviceFlag || cookie.type == CookieType.SHARED_OF_FLOW
}

def defaultHexCookies = []
defaultCookies.each { defaultHexCookies.add(Long.toHexString(it)) }
assertions.checkSucceeds {
assert switchValidateInfo.rules.properHex.findAll { !(it in defaultHexCookies) }.empty
}
} else {
assertions.checkSucceeds { assert switchValidateInfo.rules."$section".empty }
}
}
assertions.verify()
}

static boolean isDefaultMeter(MeterInfoDto dto) {
return MeterId.isMeterIdOfDefaultRule(dto.getMeterId())
}
Expand All @@ -567,25 +454,6 @@ class SwitchHelper {
return MeterId.isMeterIdOfDefaultRule(dto.getMeterId())
}

/**
* Verifies that actual and expected burst size are the same.
*/
static void verifyBurstSizeIsCorrect(Switch sw, Long expected, Long actual) {
if (sw.isWb5164()) {
assert Math.abs(expected - actual) <= expected * 0.01
} else {
assert Math.abs(expected - actual) <= 1
}
}

static void verifyRateSizeIsCorrect(Switch sw, Long expected, Long actual) {
if (sw.isWb5164()) {
assert Math.abs(expected - actual) <= expected * 0.01
} else {
assert Math.abs(expected - actual) <= 1
}
}

static SwitchProperties getDummyServer42Props() {
return new SwitchProperties(true, 33, "00:00:00:00:00:00", 1, null)
}
Expand Down Expand Up @@ -676,25 +544,6 @@ class SwitchHelper {
reviveSwitch(sw, flResourceAddress, false)
}

static void verifySectionInSwitchValidationInfo(SwitchValidationV2ExtendedResult switchValidateInfo,
List<String> sections = ["groups", "meters", "logical_ports", "rules"]) {
sections.each { String section ->
assertThat(switchValidateInfo."$section", notNullValue())
}

}

static void verifySectionsAsExpectedFields(SwitchValidationV2ExtendedResult switchValidateInfo,
List<String> sections = ["groups", "meters", "logical_ports", "rules"]) {
boolean result = true;
sections.each { String section ->
if (!switchValidateInfo."$section".asExpected) {
result = false
}
}
assert result == switchValidateInfo.asExpected
}

static SwitchSyncExtendedResult synchronize(SwitchId switchId, boolean removeExcess=true) {
return northbound.get().synchronizeSwitch(switchId, removeExcess)
}
Expand Down Expand Up @@ -755,15 +604,6 @@ class SwitchHelper {
return Optional.ofNullable(validateAndCollectFoundDiscrepancies([switchToValidate]).get(switchToValidate))
}

static void synchronizeAndValidateRulesInstallation(Switch srcSwitch, Switch dstSwitch) {
synchronizeAndCollectFixedDiscrepancies([srcSwitch.dpId, dstSwitch.dpId])
[srcSwitch, dstSwitch].each { sw ->
Wrappers.wait(RULES_INSTALLATION_TIME) {
validate(sw.dpId).verifyRuleSectionsAreEmpty()
}
}
}

static SwitchValidationV2ExtendedResult validate(SwitchId switchId, String include = null, String exclude = null) {
return northboundV2.get().validateSwitch(switchId, include, exclude)
}
Expand Down Expand Up @@ -966,13 +806,6 @@ class SwitchHelper {
return northboundV2.get().partialSwitchUpdate(switchId, updateDto)
}

static boolean isServer42Supported(SwitchId switchId) {
def swProps = northbound.get().getSwitchProperties(switchId)
def featureToggles = northbound.get().getFeatureToggles()
def isServer42 = swProps.server42FlowRtt && featureToggles.server42FlowRtt
return isServer42
}

static int randomVlan() {
return randomVlan([])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package org.openkilda.functionaltests.helpers.model
import static groovyx.gpars.GParsPool.withPool
import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.Matchers.hasItem
import static org.hamcrest.Matchers.notNullValue
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.OTHER
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.RESET_SWITCH_MAINTENANCE
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.RESTORE_SWITCH_PROPERTIES
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.REVIVE_SWITCH
import static org.openkilda.functionaltests.model.cleanup.CleanupActionType.SYNCHRONIZE_SWITCH
import static org.openkilda.messaging.info.event.IslChangeType.DISCOVERED
import static org.openkilda.messaging.info.event.IslChangeType.FAILED
import static org.openkilda.messaging.info.event.SwitchChangeType.ACTIVATED
Expand Down Expand Up @@ -210,6 +212,11 @@ class SwitchExtended {
return new PortExtended(sw, portNo, northbound, northboundV2, cleanupManager)
}

PortExtended getPortInState(String state) {
Integer portNo = northbound.getPorts(switchId).find { state in it.state }.portNumber
return new PortExtended(sw, portNo, northbound, northboundV2, cleanupManager)
}

LagPort getLagPort(Set<Integer> portNumbers) {
new LagPort(switchId, portNumbers, northboundV2, cleanupManager)
}
Expand Down Expand Up @@ -413,7 +420,8 @@ class SwitchExtended {
* reinstalled according to config
*/
SwitchPropertiesDto updateProperties(SwitchPropertiesDto switchProperties) {
cleanupManager.addAction(OTHER, { northbound.updateSwitchProperties(sw.dpId, getCashedProps()) })
def initialProps = getCashedProps()
cleanupManager.addAction(OTHER, { northbound.updateSwitchProperties(sw.dpId, initialProps) })
def response = northbound.updateSwitchProperties(sw.dpId, switchProperties)
Wrappers.wait(RULES_INSTALLATION_TIME) {
def actualHexCookie = []
Expand Down Expand Up @@ -528,6 +536,10 @@ class SwitchExtended {
return northbound.deleteSwitch(sw.dpId, force)
}

SwitchPropertiesDto getPropsV1() {
northbound.getSwitchProperties(sw.dpId)
}

SwitchConnectedDevicesResponse getConnectedDevices() {
northboundV2.getConnectedDevices(switchId)
}
Expand Down Expand Up @@ -633,6 +645,11 @@ class SwitchExtended {
revive(flResourceAddress, false)
}

void updateBurstSizeAndRate(Long meterId, Long newBurstSize, Long newRate) {
cleanupManager.addAction(SYNCHRONIZE_SWITCH, { synchronize() })
lockKeeper.updateBurstSizeAndRate(sw, meterId, newBurstSize, newRate)
}

void verifyRelatedLinksState(IslChangeType expectedState) {
def relatedLinks = collectForwardAndReverseRelatedLinks()
assert relatedLinks.size() == islPorts.size() * 2
Expand Down Expand Up @@ -702,6 +719,11 @@ class SwitchExtended {
database.getSwitch(sw.dpId).features
}

void setFeaturesInDb(Set<SwitchFeature> features) {
cleanupManager.addAction(OTHER, { database.setSwitchFeatures(sw.dpId, getDbFeatures())})
database.setSwitchFeatures(sw.dpId, features)
}

boolean isVxlanFeatureEnabled() {
!getDbFeatures().intersect([NOVIFLOW_PUSH_POP_VXLAN, KILDA_OVS_PUSH_POP_MATCH_VXLAN]).isEmpty()
}
Expand Down Expand Up @@ -896,4 +918,22 @@ class SwitchExtended {
}
assertions.verify()
}

static void verifySectionInSwitchValidationInfo(SwitchValidationV2ExtendedResult switchValidateInfo,
List<String> sections = ["groups", "meters", "logical_ports", "rules"]) {
sections.each { String section ->
assertThat(switchValidateInfo."$section", notNullValue())
}
}

static void verifySectionsAsExpectedFields(SwitchValidationV2ExtendedResult switchValidateInfo,
List<String> sections = ["groups", "meters", "logical_ports", "rules"]) {
boolean result = true;
sections.each { String section ->
if (!switchValidateInfo."$section".asExpected) {
result = false
}
}
assert result == switchValidateInfo.asExpected
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.openkilda.functionaltests.helpers.model

import static groovyx.gpars.GParsPool.withPool
import static org.junit.jupiter.api.Assumptions.assumeFalse
import static org.junit.jupiter.api.Assumptions.assumeTrue
import static org.openkilda.functionaltests.helpers.model.SwitchExtended.isS42Supported
import static org.openkilda.functionaltests.model.switches.Manufacturer.CENTEC
import static org.openkilda.functionaltests.model.switches.Manufacturer.NOVIFLOW
Expand All @@ -12,6 +13,7 @@ import static org.springframework.beans.factory.config.ConfigurableBeanFactory.S

import org.openkilda.functionaltests.helpers.factory.SwitchFactory
import org.openkilda.functionaltests.model.switches.Manufacturer
import org.openkilda.model.SwitchFeature
import org.openkilda.model.SwitchId
import org.openkilda.northbound.dto.v1.switches.SwitchDto
import org.openkilda.testing.model.topology.TopologyDefinition
Expand Down Expand Up @@ -77,6 +79,10 @@ class Switches {
switches.findAll().unique { it.hwSwString()}
}

List<SwitchExtended> notOF12Version() {
switches.findAll { it.ofVersion != "OF_12" }
}

Switches withS42Support(){
def swsProps = northboundV2.getAllSwitchProperties().switchProperties
switches = switches.findAll { sw -> isS42Supported(swsProps.find { it.switchId == sw.switchId}) }
Expand Down Expand Up @@ -104,6 +110,11 @@ class Switches {
return this
}

Switches withoutLagSupport() {
switches = switches.findAll { !it.dbFeatures.contains(SwitchFeature.LAG) }
return this
}

SwitchExtended random() {
assumeFalse(switches.isEmpty(), "No suiting switch found")
switches.shuffled().first()
Expand Down Expand Up @@ -139,6 +150,12 @@ class Switches {
desiredSwitches
}

SwitchExtended findWithVxlanFeatureEnabled() {
def sw = switches.find { it.isVxlanFeatureEnabled() }
assumeTrue(sw as Boolean, "No suiting switch(vxlan-enabled) found")
sw
}

@Memoized
private List<SwitchExtended> collectSwitches() {
List<SwitchDto> switchesDetails = northbound.allSwitches
Expand Down
Loading

0 comments on commit 44e778c

Please sign in to comment.