blob: cbbf87ed09f2420145cdb2ebf1fd9f3f8c3c0dc2 [file] [log] [blame]
""" Defined Some common functions used by Conformance tests -- OF-SWITCH 1.0.0 Testcases """
import sys
import copy
import random
import oftest.controller as controller
import oftest.cstruct as ofp
import oftest.message as message
import oftest.dataplane as dataplane
import oftest.action as action
import oftest.parse as parse
import logging
import types
import oftest.base_tests as base_tests
from oftest.testutils import *
from time import sleep
#################### Functions for various types of flow_mod ##########################################################################################
def match_send_flowadd(self, match, priority, port):
msg = message.flow_mod()
msg.out_port = ofp.OFPP_NONE
msg.command = ofp.OFPFC_ADD
# msg.cookie = random.randint(0,9007199254740992)
msg.buffer_id = 0xffffffff
msg.match = match
if priority != None :
msg.priority = priority
act = action.action_output()
act.port = port
msg.actions.add(act)
self.controller.message_send(msg)
do_barrier(self.controller)
def exact_match(self,of_ports,priority=None):
# Generate ExactMatch flow .
#Create a simple tcp packet and generate exact flow match from it.
pkt_exactflow = simple_tcp_packet()
match = parse.packet_to_flow_match(pkt_exactflow)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.in_port = of_ports[0]
#match.nw_src = 1
match.wildcards=0
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_exactflow,match)
def exact_match_with_prio(self,of_ports,priority=None):
# Generate ExactMatch with action output to port 2
#Create a simple tcp packet and generate exact flow match from it.
pkt_exactflow = simple_tcp_packet()
match = parse.packet_to_flow_match(pkt_exactflow)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.in_port = of_ports[0]
#match.nw_src = 1
match.wildcards=0
match_send_flowadd(self, match, priority, of_ports[2])
return (pkt_exactflow,match)
def match_all_except_source_address(self,of_ports,priority=None):
# Generate Match_All_Except_Source_Address flow
#Create a simple tcp packet and generate match all except src address flow.
pkt_wildcardsrc= simple_tcp_packet()
match1 = parse.packet_to_flow_match(pkt_wildcardsrc)
self.assertTrue(match1 is not None, "Could not generate flow match from pkt")
match1.in_port = of_ports[0]
#match1.nw_src = 1
match1.wildcards = ofp.OFPFW_DL_SRC
match_send_flowadd(self, match1, priority, of_ports[1])
return (pkt_wildcardsrc,match1)
def match_ethernet_src_address(self,of_ports,priority=None):
#Generate Match_Ethernet_SrC_Address flow
#Create a simple tcp packet and generate match on ethernet src address flow
pkt_MatchSrc = simple_eth_packet(dl_src='00:01:01:01:01:01')
match = parse.packet_to_flow_match(pkt_MatchSrc)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_SRC
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_MatchSrc,match)
def match_ethernet_dst_address(self,of_ports,priority=None):
#Generate Match_Ethernet_Dst_Address flow
#Create a simple tcp packet and generate match on ethernet dst address flow
pkt_matchdst = simple_eth_packet(dl_dst='00:01:01:01:01:01')
match = parse.packet_to_flow_match(pkt_matchdst)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_DST
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchdst,match)
def wildcard_all(self,of_ports,priority=None):
# Generate a Wildcard_All Flow
#Create a simple tcp packet and generate wildcard all flow match from it.
pkt_wildcard = simple_tcp_packet()
match2 = parse.packet_to_flow_match(pkt_wildcard)
self.assertTrue(match2 is not None, "Could not generate flow match from pkt")
match2.wildcards=ofp.OFPFW_ALL
match2.in_port = of_ports[0]
match_send_flowadd(self, match2, priority, of_ports[1])
return (pkt_wildcard,match2)
def wildcard_all_except_ingress(self,of_ports,priority=None):
# Generate Wildcard_All_Except_Ingress_port flow
#Create a simple tcp packet and generate wildcard all except ingress_port flow.
pkt_matchingress = simple_tcp_packet()
match3 = parse.packet_to_flow_match(pkt_matchingress)
self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
match3.in_port = of_ports[0]
match_send_flowadd(self, match3, priority, of_ports[1])
return (pkt_matchingress,match3)
def wildcard_all_except_ingress1(self,of_ports,priority=None):
# Generate Wildcard_All_Except_Ingress_port flow with action output to port egress_port 2
#Create a simple tcp packet and generate wildcard all except ingress_port flow.
pkt_matchingress = simple_tcp_packet()
match3 = parse.packet_to_flow_match(pkt_matchingress)
self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
match3.in_port = of_ports[0]
match_send_flowadd(self, match3, priority, of_ports[2])
return (pkt_matchingress,match3)
def match_vlan_id(self,of_ports,priority=None):
#Generate Match_Vlan_Id
#Create a simple tcp packet and generate match on ethernet dst address flow
pkt_matchvlanid = simple_tcp_packet(dl_vlan_enable=True,dl_vlan=1)
match = parse.packet_to_flow_match(pkt_matchvlanid)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_DL_VLAN
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchvlanid,match)
def match_vlan_pcp(self,of_ports,priority=None):
#Generate Match_Vlan_Priority
#Create a simple tcp packet and generate match on ethernet dst address flow
pkt_matchvlanpcp = simple_tcp_packet(dl_vlan_enable=True,dl_vlan=1,dl_vlan_pcp=5)
match = parse.packet_to_flow_match(pkt_matchvlanpcp)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_TYPE^ofp.OFPFW_DL_VLAN^ofp.OFPFW_DL_VLAN_PCP
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchvlanpcp,match)
def match_mul_l2(self,of_ports,priority=None):
#Generate Match_Mul_L2 flow
#Create a simple eth packet and generate match on ethernet protocol flow
pkt_mulL2 = simple_eth_packet(dl_type=0x88cc,dl_src='00:01:01:01:01:01',dl_dst='00:01:01:01:01:02')
match = parse.packet_to_flow_match(pkt_mulL2)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_DL_DST ^ofp.OFPFW_DL_SRC
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_mulL2,match)
def match_mul_l4(self,of_ports,priority=None):
#Generate Match_Mul_L4 flow
#Create a simple tcp packet and generate match on tcp protocol flow
pkt_mulL4 = simple_tcp_packet(tcp_sport=111,tcp_dport=112)
match = parse.packet_to_flow_match(pkt_mulL4)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO^ofp.OFPFW_TP_SRC ^ofp.OFPFW_TP_DST
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_mulL4,match)
def match_ip_tos(self,of_ports,priority=None):
#Generate a Match on IP Type of service flow
#Create a simple tcp packet and generate match on Type of service
pkt_iptos = simple_tcp_packet(ip_tos=28)
match = parse.packet_to_flow_match(pkt_iptos)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_NW_TOS
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_iptos,match)
def match_ip_protocol(self,of_ports,priority=None):
#Generate a Match on IP Protocol
#Create a simple tcp packet and generate match on Type of service
pkt_iptos = simple_tcp_packet()
match = parse.packet_to_flow_match(pkt_iptos)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE^ofp.OFPFW_NW_PROTO
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_iptos,match)
def match_tcp_src(self,of_ports,priority=None):
#Generate Match_Tcp_Src
#Create a simple tcp packet and generate match on tcp source port flow
pkt_matchtSrc = simple_tcp_packet(tcp_sport=111)
match = parse.packet_to_flow_match(pkt_matchtSrc)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_TP_SRC
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchtSrc,match)
def match_tcp_dst(self,of_ports,priority=None):
#Generate Match_Tcp_Dst
#Create a simple tcp packet and generate match on tcp destination port flow
pkt_matchdst = simple_tcp_packet(tcp_dport=112)
match = parse.packet_to_flow_match(pkt_matchdst)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_TYPE^ofp.OFPFW_NW_PROTO^ofp.OFPFW_TP_DST
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchdst,match)
def match_udp_src(self,of_ports,priority=None):
#Generate Match_Udp_Src
#Create a simple udp packet and generate match on udp source port flow
pkt_matchtSrc = simple_udp_packet(udp_sport=111)
match = parse.packet_to_flow_match(pkt_matchtSrc)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_TP_SRC
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchtSrc,match)
def match_udp_dst(self,of_ports,priority=None):
#Generate Match_Udp_Dst
#Create a simple udp packet and generate match on udp destination port flow
pkt_matchdst = simple_udp_packet(udp_dport=112)
match = parse.packet_to_flow_match(pkt_matchdst)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_TYPE^ofp.OFPFW_NW_PROTO^ofp.OFPFW_TP_DST
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchdst,match)
def match_icmp_type(self,of_ports,priority=None):
#Generate Match_Icmp_Type
#Create a simple icmp packet and generate match on icmp type flow
pkt_match = simple_icmp_packet(icmp_type=1)
match = parse.packet_to_flow_match(pkt_match)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_TP_SRC
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_match, match)
def match_icmp_code(self,of_ports,priority=None):
#Generate Match_Icmp_Code
#Create a simple icmp packet and generate match on icmp code flow
pkt_match = simple_icmp_packet(icmp_code=3)
match = parse.packet_to_flow_match(pkt_match)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_TP_DST
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_match, match)
def match_arp_sender(self,of_ports,priority=None):
#Generate Match_Arp_Sender
#Create a simple icmp packet and generate match on arp sender flow
pkt_match = simple_arp_packet()
match = parse.packet_to_flow_match(pkt_match)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_NW_SRC_MASK
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_match, match)
def match_arp_target(self,of_ports,priority=None):
#Generate Match_Arp_Target
#Create a simple icmp packet and generate match on arp target flow
pkt_match = simple_arp_packet()
match = parse.packet_to_flow_match(pkt_match)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL^ofp.OFPFW_DL_TYPE ^ofp.OFPFW_NW_PROTO ^ofp.OFPFW_NW_DST_MASK
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_match, match)
def match_ethernet_type(self,of_ports,priority=None):
#Generate a Match_Ethernet_Type flow
#Create a simple tcp packet and generate match on ethernet type flow
pkt_matchtype = simple_eth_packet(dl_type=0x88cc)
match = parse.packet_to_flow_match(pkt_matchtype)
self.assertTrue(match is not None, "Could not generate flow match from pkt")
match.wildcards = ofp.OFPFW_ALL ^ofp.OFPFW_DL_TYPE
match_send_flowadd(self, match, priority, of_ports[1])
return (pkt_matchtype,match)
def strict_modify_flow_action(self,egress_port,match,priority=None):
# Strict Modify the flow Action
#Create a flow_mod message , command MODIFY_STRICT
msg5 = message.flow_mod()
msg5.match = match
msg5.cookie = random.randint(0,9007199254740992)
msg5.command = ofp.OFPFC_MODIFY_STRICT
msg5.buffer_id = 0xffffffff
act5 = action.action_output()
act5.port = egress_port
msg5.actions.add(act5)
if priority != None :
msg5.priority = priority
# Send the flow with action A'
self.controller.message_send (msg5)
do_barrier(self.controller)
def modify_flow_action(self,of_ports,match,priority=None):
# Modify the flow action
#Create a flow_mod message , command MODIFY
msg8 = message.flow_mod()
msg8.match = match
msg8.cookie = random.randint(0,9007199254740992)
msg8.command = ofp.OFPFC_MODIFY
#out_port will be ignored for flow adds and flow modify (here for test-case Add_Modify_With_Outport)
msg8.out_port = of_ports[3]
msg8.buffer_id = 0xffffffff
act8 = action.action_output()
act8.port = of_ports[2]
msg8.actions.add(act8)
if priority != None :
msg8.priority = priority
# Send the flow with action A'
self.controller.message_send (msg8)
do_barrier(self.controller)
def enqueue(self,ingress_port,egress_port,egress_queue_id):
#Generate a flow with enqueue action i.e output to a queue configured on a egress_port
pkt = simple_tcp_packet()
match = packet_to_flow_match(self, pkt)
match.wildcards &= ~ofp.OFPFW_IN_PORT
self.assertTrue(match is not None,
"Could not generate flow match from pkt")
match.in_port = ingress_port
request = message.flow_mod()
request.match = match
request.buffer_id = 0xffffffff
act = action.action_enqueue()
act.port = egress_port
act.queue_id = egress_queue_id
request.actions.add(act)
logging.info("Inserting flow")
self.controller.message_send(request)
do_barrier(self.controller)
return (pkt,match)
########################### Verify Stats Functions ###########################################################################################
def get_flowstats(self,match):
# Generate flow_stats request
stat_req = message.flow_stats_request()
stat_req.match = match
stat_req.table_id = 0xff
stat_req.out_port = ofp.OFPP_NONE
logging.info("Sending stats request")
response, pkt = self.controller.transact(stat_req,
timeout=5)
self.assertTrue(response is not None,"No response to stats request")
def get_portstats(self,port_num):
# Return all the port counters in the form a tuple
port_stats_req = message.port_stats_request()
port_stats_req.port_no = port_num
response,pkt = self.controller.transact(port_stats_req)
self.assertTrue(response is not None,"No response received for port stats request")
rx_pkts=0
tx_pkts=0
rx_byts=0
tx_byts=0
rx_drp =0
tx_drp = 0
rx_err=0
tx_err =0
rx_fr_err=0
rx_ovr_err=0
rx_crc_err=0
collisions = 0
tx_err=0
for obj in response.stats:
rx_pkts += obj.rx_packets
tx_pkts += obj.tx_packets
rx_byts += obj.rx_bytes
tx_byts += obj.tx_bytes
rx_drp += obj.rx_dropped
tx_drp += obj.tx_dropped
rx_err += obj.rx_errors
rx_fr_err += obj.rx_frame_err
rx_ovr_err += obj.rx_over_err
rx_crc_err += obj.rx_crc_err
collisions+= obj.collisions
tx_err += obj.tx_errors
return (rx_pkts,tx_pkts,rx_byts,tx_byts,rx_drp,tx_drp,rx_err,tx_err,rx_fr_err,rx_ovr_err,rx_crc_err,collisions,tx_err)
def get_queuestats(self,port_num,queue_id):
#Generate Queue Stats request
request = message.queue_stats_request()
request.port_no = port_num
request.queue_id = queue_id
(queue_stats, p) = self.controller.transact(request)
self.assertNotEqual(queue_stats, None, "Queue stats request failed")
return (queue_stats,p)
def get_tablestats(self):
# Send Table_Stats request (retrieve current table counters )
stat_req = message.table_stats_request()
response, pkt = self.controller.transact(stat_req,
timeout=5)
self.assertTrue(response is not None,
"No response to stats request")
current_lookedup = 0
current_matched = 0
current_active = 0
for obj in response.stats:
current_lookedup += obj.lookup_count
current_matched += obj.matched_count
current_active += obj.active_count
return (current_lookedup,current_matched,current_active)
def verify_tablestats(self,expect_lookup=None,expect_match=None,expect_active=None):
stat_req = message.table_stats_request()
for i in range(0,100):
logging.info("Sending stats request")
# TODO: move REPLY_MORE handling to controller.transact?
response, pkt = self.controller.transact(stat_req,
timeout=5)
self.assertTrue(response is not None,"No response to stats request")
lookedup = 0
matched = 0
active = 0
for item in response.stats:
lookedup += item.lookup_count
matched += item.matched_count
active += item.active_count
logging.info("Packets Looked up: %d", lookedup)
logging.info("Packets matched: %d", matched)
logging.info("Active flow entries: %d", active)
if (expect_lookup == None or lookedup >= expect_lookup) and \
(expect_match == None or matched >= expect_match) and \
(expect_active == None or active >= expect_active):
break
sleep(0.1)
if expect_lookup != None :
self.assertEqual(expect_lookup, lookedup, "lookup counter is not incremented properly")
if expect_match != None :
self.assertEqual(expect_match, matched, "matched counter is not incremented properly")
if expect_active != None :
self.assertEqual(expect_active, active ,"active counter is not incremented properly")
############################## Various delete commands #############################################################################################
def strict_delete(self,match,priority=None):
# Issue Strict Delete
#Create flow_mod message, command DELETE_STRICT
msg4 = message.flow_mod()
msg4.out_port = ofp.OFPP_NONE
msg4.command = ofp.OFPFC_DELETE_STRICT
msg4.buffer_id = 0xffffffff
msg4.match = match
if priority != None :
msg4.priority = priority
self.controller.message_send(msg4)
do_barrier(self.controller)
def nonstrict_delete(self,match,priority=None):
# Issue Non_Strict Delete
#Create flow_mod message, command DELETE
msg6 = message.flow_mod()
msg6.out_port = ofp.OFPP_NONE
msg6.command = ofp.OFPFC_DELETE
msg6.buffer_id = 0xffffffff
msg6.match = match
if priority != None :
msg6.priority = priority
self.controller.message_send(msg6)
do_barrier(self.controller)
###########################################################################################################################################################
def send_packet(obj, pkt, ingress_port, egress_port):
#Send Packets on a specified ingress_port and verify if its recieved on correct egress_port.
obj.dataplane.send(ingress_port, str(pkt))
exp_pkt_arg = pkt
exp_port = egress_port
(rcv_port, rcv_pkt, pkt_time) = obj.dataplane.poll(timeout=2,
port_number=exp_port,
exp_pkt=exp_pkt_arg)
obj.assertTrue(rcv_pkt is not None,
"Packet not received on port " + str(egress_port))
obj.assertEqual(rcv_port, egress_port,
"Packet received on port " + str(rcv_port) +
", expected port " + str(egress_port))
obj.assertEqual(str(pkt), str(rcv_pkt),
'Response packet does not match send packet')
def sw_supported_actions(parent,use_cache=False):
#Returns the switch's supported actions
cache_supported_actions = None
if cache_supported_actions is None or not use_cache:
request = message.features_request()
(reply, pkt) = parent.controller.transact(request)
parent.assertTrue(reply is not None, "Did not get response to ftr req")
cache_supported_actions = reply.actions
return cache_supported_actions
##############################################################################################################################################################