blob: 7e6f36b19c4535927341e56f1c658db8fcb90a32 [file] [log] [blame]
# Copyright 2017-present Open Networking Foundation
#
# 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.
"""These tests fall under Conformance Test-Suite (OF-SWITCH-1.0.0 TestCases).
Refer Documentation -- Detailed testing methodology
<Some of test-cases are directly taken from oftest> """
"Test Suite 5 --> Counters"
import logging
import unittest
import random
from oftest import config
import oftest.controller as controller
import ofp
import oftest.dataplane as dataplane
import oftest.parse as parse
import oftest.base_tests as base_tests
import time
from oftest.testutils import *
from time import sleep
from FuncUtils import*
def port_queues_get(self, queue_stats, port_num):
result = []
for qs in queue_stats.entries:
if qs.port_no != port_num:
continue
result.append(qs.queue_id)
return result
class PktPerFlow(base_tests.SimpleDataPlane):
"""Verify Packet counters per flow are
incremented by no. of packets received for that flow"""
def runTest(self):
logging.info("Running PktPerFlow test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch state
delete_all_flows(self.controller)
logging.info("Insert any flow")
logging.info("Sending N Packets matching the flow")
logging.info("Verify packet counters increment in accordance")
#Create a Match on Ingress flow
(pkt,match) = wildcard_all_except_ingress(self,of_ports)
#Send Packets matching the flow
num_pkts = 5
for pkt_cnt in range(num_pkts):
self.dataplane.send(of_ports[0],str(pkt))
# Verify the packet counter was updated
verify_flow_stats(self, match, pkts=num_pkts)
class BytPerFlow(base_tests.SimpleDataPlane):
"""Verify Byte counters per flow are
incremented by no. of bytes received for that flow"""
def runTest(self):
logging.info("Running BytPerFlow test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch state
delete_all_flows(self.controller)
logging.info("Insert any flow")
logging.info("Sending N Packets matching the flow")
logging.info("Verify byte counters increment in accordance")
#Create a Match on Ingress flow
(pkt,match) = wildcard_all_except_ingress(self,of_ports)
#Send Packets matching the flow
num_pkts = 5
byte_count = num_pkts*len(str(pkt))
for pkt_cnt in range(num_pkts):
self.dataplane.send(of_ports[0],str(pkt))
# Verify the byte counter was updated
verify_flow_stats(self, match, bytes=byte_count)
class DurationPerFlow(base_tests.SimpleDataPlane):
"""Verify Duration_sec and Duration_nsec counters per flow varies in accordance with the amount of
time the flow was alive"""
def runTest(self):
logging.info("Running DurationPerFlow test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch state
delete_all_flows(self.controller)
logging.info("Insert any flow")
logging.info("Send Flow_stats request after n sec intervals")
logging.info("Verify duration_sec and nsec counters are incrementing in accordance with the life of flow")
#Create a flow with match on ingress_port
(pkt,match) = wildcard_all_except_ingress(self,of_ports)
#Create flow_stats request
stat_req = ofp.message.flow_stats_request()
stat_req.match= match
stat_req.table_id = 0xff
stat_req.out_port = ofp.OFPP_NONE
expected_duration = 3
sleep(expected_duration)
response, pkt = self.controller.transact(stat_req)
self.assertTrue(response is not None,"No response to stats request")
self.assertTrue(len(response.entries) == 1,"Did not receive flow stats reply")
stat = response.entries[0]
logging.info("Duration of flow is %d s %d ns", stat.duration_sec, stat.duration_nsec)
self.assertTrue(stat.duration_sec == expected_duration, "Flow stats reply incorrect")
class RxPktPerPort(base_tests.SimpleDataPlane):
"""Verify that rx_packets counter in the Port_Stats reply
increments when packets are received on a port"""
def runTest(self):
logging.info("Running RxPktPerPort test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
# Clear Switch State
delete_all_flows(self.controller)
logging.info("Insert a flow with match on ingress_port")
logging.info("Send N Packets on an ingress_port P ")
logging.info("Send Port_Stats Request for Port P , verify recieved packets counters are incrementing in accordance")
#Insert a flow with match on all ingress port
(pkt, match ) = wildcard_all_except_ingress(self,of_ports)
# Send Port_Stats request for the ingress port (retrieve old counter state)
initial_stats = get_port_stats(self, of_ports[0])
# Send packets matching the flow
num_pkts = 5
for pkt_cnt in range(num_pkts):
self.dataplane.send(of_ports[0],str(pkt))
#Verify recieved packet counters
verify_port_stats(self, of_ports[0], initial=initial_stats, rx_pkts=num_pkts)
class TxPktPerPort(base_tests.SimpleDataPlane):
"""Verify that tx_packets counter in the Port_Stats reply , increments when packets are transmitted by a port"""
def runTest(self):
logging.info("Running TxPktPerPort test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch state
delete_all_flows(self.controller)
logging.info("Insert any flow matching on in_port=ingress_port, action output to egress_port T ")
logging.info("Send N Packets matching the flow on ingress_port P ")
logging.info("Send Port_Stats Request for Port T , verify transmitted packets counters are incrementing in accordance")
#Insert a flow with match on all ingress port
(pkt,match) = wildcard_all_except_ingress(self,of_ports)
# Send Port_Stats request for the egress port (retrieve old counter state)
initial_stats = get_port_stats(self, of_ports[1])
#Send packets matching the flow
num_pkts = 5
for pkt_cnt in range(num_pkts):
self.dataplane.send(of_ports[0],str(pkt))
#Verify transmitted_packet counters
verify_port_stats(self, of_ports[1], initial=initial_stats,
tx_pkts=num_pkts)
class RxBytPerPort(base_tests.SimpleDataPlane):
"""Verify that recieved bytes counter in the Port_Stats reply , increments in accordance with the bytes recieved on a port"""
def runTest(self):
logging.info("Running RxBytPerPort test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Insert any flow matching on in_port=ingress_port")
logging.info("Send N Packets matching the flow on ingress_port P ")
logging.info("Send Port_Stats Request for Port P , verify recieved bytes counters are incrementing in accordance")
#Insert a flow with match on all ingress port
(pkt, match ) = wildcard_all_except_ingress(self,of_ports)
# Send Port_Stats request for the ingress port (retrieve current counter state)
initial_stats = get_port_stats(self, of_ports[0])
#Send packets matching the flow.
num_pkts = 5
byte_count = num_pkts*len(str(pkt))
for pkt_cnt in range(num_pkts):
self.dataplane.send(of_ports[0],str(pkt))
#Verify recieved_bytes counters
verify_port_stats(self, of_ports[0], initial=initial_stats,
rx_bytes=byte_count)
class TxBytPerPort(base_tests.SimpleDataPlane):
"""Verify that trasnsmitted bytes counter in the Port_Stats reply , increments in accordance with the bytes trasmitted by a port"""
def runTest(self):
logging.info("Running TxBytPerPort test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Insert any flow matching on in_port=ingress_port,action = output to egress_port T")
logging.info("Send N Packets matching the flow on ingress_port P ")
logging.info("Send Port_Stats Request for Port T , verify trasmitted bytes counters are incrementing in accordance")
#Insert a flow with match on all ingress port
(pkt, match ) = wildcard_all_except_ingress(self,of_ports)
# Send Port_Stats request for the egress port (retrieve current counter state)
initial_stats = get_port_stats(self, of_ports[1])
#Send packets matching the flow.
num_pkts = 5
byte_count = num_pkts*len(str(pkt))
for pkt_cnt in range(num_pkts):
self.dataplane.send(of_ports[0],str(pkt))
#Verify trasmitted_bytes counters
verify_port_stats(self, of_ports[1], initial=initial_stats,
tx_bytes=byte_count)
class ActiveCount(base_tests.SimpleDataPlane):
"""Verify that active_count counter in the Table_Stats reply , increments in accordance with the flows inserted in a table"""
def runTest(self):
logging.info("Running Table_Counter_1 test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear Switch state
delete_all_flows(self.controller)
logging.info("Insert any flow matching on in_port=ingress_port,action = output to egress_port T ")
logging.info("Send Table_Stats, verify active_count counter is incremented in accordance")
#Insert a flow with match on all ingress port
(pkt, match ) = wildcard_all_except_ingress(self,of_ports)
#Generate Table_Stats
verify_tablestats(self,expect_active=1)
class LookupMatchedCount(base_tests.SimpleDataPlane):
"""Verify that lookup_count and matched_count counter in the Table_Stats reply
increments in accordance with the packets looked up and matched with the flows in the table"""
def runTest(self):
logging.info("Running LookupMatchedCount test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear Switch state
delete_all_flows(self.controller)
logging.info("Insert any flow matching on in_port=ingress_port,action = output to egress_port")
logging.info("Send N packets matching the flow, N' packets not matching the flow")
logging.info("Send Table_Stats, verify lookup_count = N+N' & matched_count=N ")
#Get Current Table Stats
(current_lookedup,current_matched,current_active) = get_tablestats(self)
#Insert a flow with match on all ingress port
(pkt, match ) = wildcard_all_except_ingress(self,of_ports)
#send packet pkt N times (pkt matches the flow)
num_sends = 5
for pkt_cnt in range(num_sends):
self.dataplane.send(of_ports[0],str(pkt))
#send packet pkt N' (pkt does not match the flow)
num_sends2 = 5
for pkt_cnt in range(num_sends):
self.dataplane.send(of_ports[1],str(pkt))
new_lookup = num_sends+num_sends2+current_lookedup
new_matched = num_sends+current_matched
#Verify lookup_count and matched_count counters.
verify_tablestats(self,expect_lookup=new_lookup,expect_match=new_matched)
class TxPktPerQueue(base_tests.SimpleDataPlane):
"""Verify that tx_packets in the queue_stats reply increments in accordance with the number of transmitted packets"""
def runTest(self):
logging.info("Running TxPktPerQueue test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
# Get queue stats from switch (retrieve current state)
(queue_stats,p) = get_queuestats(self,ofp.OFPP_ALL,ofp.OFPQ_ALL)
for idx in range(len(of_ports)):
ingress_port = of_ports[idx]
egress_port = of_ports[(idx + 1) % len(of_ports)]
queue_id = port_queues_get(self,queue_stats,egress_port)
for egress_queue_id in queue_id:
#Clear switch state
delete_all_flows(self.controller)
# Get Queue stats for selected egress queue only
initial_stats = get_queue_stats(self, egress_port, egress_queue_id)
#Insert a flow with enqueue action to queues configured on egress_port
(pkt,match) = enqueue(self,ingress_port,egress_port,egress_queue_id)
#Send packet on the ingress_port and verify its received on egress_port
send_packet(self,pkt,ingress_port,egress_port)
verify_queue_stats(self, egress_port, egress_queue_id,
initial=initial_stats, pkts=1)
class TxBytPerQueue(base_tests.SimpleDataPlane):
"""Verify that tx_bytes in the queue_stats reply increments in accordance with the number of transmitted bytes"""
def runTest(self):
logging.info("Running TxBytPerQueue test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
# Get queue stats from switch (retrieve current state)
(queue_stats,p) = get_queuestats(self,ofp.OFPP_ALL,ofp.OFPQ_ALL)
for idx in range(len(of_ports)):
ingress_port = of_ports[idx]
egress_port = of_ports[(idx + 1) % len(of_ports)]
queue_id = port_queues_get(self,queue_stats,egress_port)
for egress_queue_id in queue_id:
#Clear switch state
delete_all_flows(self.controller)
# Get Queue stats for selected egress queue only
initial_stats = get_queue_stats(self, egress_port, egress_queue_id)
#Insert a flow with enqueue action to queues configured on egress_port
(pkt,match) = enqueue(self,ingress_port,egress_port,egress_queue_id)
#Send packet on the ingress_port and verify its received on egress_port
send_packet(self,pkt,ingress_port,egress_port)
verify_queue_stats(self, egress_port, egress_queue_id,
initial=initial_stats,
bytes=len(str(pkt)))
class RxDrops(base_tests.SimpleDataPlane):
"""Verify that rx_dropped counters in the Port_Stats reply increments in accordance with the packets dropped by RX"""
def runTest(self):
logging.info("Running Rx_Drops test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has rx_dropped count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
rx_drp = counter[4]
logging.info("recieved dropped count is :" + str(rx_drp))
class TxDrops(base_tests.SimpleDataPlane):
"""Verify that tx_dropped counters in the Port_Stats reply increments in accordance with the packets dropped by TX"""
def runTest(self):
logging.info("Running Tx_Drops test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has tx_dropped count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[1])
tx_drp = counter[5]
logging.info("Transmitted dropped count is :" + str(tx_drp))
class RxErrors(base_tests.SimpleDataPlane):
"""Verify that rx_errors counters in the Port_Stats reply increments in accordance with number of recieved error
This is a super-set of more specific receive errors and should be greater than or equal to the sum of all
rx_*_err values"""
def runTest(self):
logging.info("Running Rx_Errors test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has rx_errors count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
rx_err = counter[6]
logging.info("Recieve Errors count is :" + str(rx_err))
class TxErrors(base_tests.SimpleDataPlane):
"""Verify that Tx_errors counters in the Port_Stats reply increments in accordance with number of trasmit error"""
def runTest(self):
logging.info("Running Tx_Errors test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has Tx_errors count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
tx_err = counter[7]
logging.info("Trasmit Error count is :" + str(tx_err))
class RxFrameErr(base_tests.SimpleDataPlane):
"""Verify that rx_frm_err counters in the Port_Stats reply increments in accordance with the number of frame alignment errors"""
def runTest(self):
logging.info("Running Rx_Frame_Err test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has rx_frame_err count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
rx_fr_err = counter[8]
logging.info("Recieve Frame Errors count is :" + str(rx_fr_err))
class RxOErr(base_tests.SimpleDataPlane):
"""Verify that rx_over_err counters in the Port_Stats reply increments in accordance with the number of with RX overrun"""
def runTest(self):
logging.info("Running Rx_O_Err test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has rx_over_err count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
rx_over_err = counter[9]
logging.info("Recieve Overrun Errors count is :" + str(rx_over_err))
class RxCrcErr(base_tests.SimpleDataPlane):
"""Verify that rx_crc_err counters in the Port_Stats reply increments in accordance with the number of crc errors"""
def runTest(self):
logging.info("Running Port_Counter_9 test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has rx_crc_err count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
rx_crc_err = counter[10]
logging.info("Recieve CRC Errors count is :" + str(rx_crc_err))
class Collisions(base_tests.SimpleDataPlane):
"""Verify that collisons counters in the Port_Stats reply increments in accordance with the collisions encountered by the switch """
def runTest(self):
logging.info("Running Collisions test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Port_Stats Request")
logging.info("Verify reply has Collisions count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
collisions = counter[11]
logging.info("collisions count is :" + str(collisions))
class TxErrorPerQueue(base_tests.SimpleDataPlane):
"""Verify that tx_errors in the queue_stats reply increments in accordance with the number of packets dropped due to overrun """
def runTest(self):
logging.info("Running TxErrorPerQueue test")
of_ports = config["port_map"].keys()
of_ports.sort()
self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
#Clear switch State
delete_all_flows(self.controller)
logging.info("Send Queue_Stats Request")
logging.info("Verify reply has Tramitted Overrun errors count ")
# Send Port_Stats request for the ingress port (retrieve current counter state)
(counter) = get_portstats(self,of_ports[0])
tx_err = counter[12]
logging.info("Transmit Overrun Error count is :" + str(tx_err))