Merge branch 'fix-1.2'
diff --git a/src/python/oftest/controller.py b/src/python/oftest/controller.py
index d802717..bee9ab9 100644
--- a/src/python/oftest/controller.py
+++ b/src/python/oftest/controller.py
@@ -608,7 +608,8 @@
self.logger.debug("Looking for %s", exp_msg_str)
for i in range(len(self.packets)):
msg = self.packets[i][0]
- self.logger.debug("Checking packets[%d] (%s)", i, exp_msg_str)
+ msg_str = ofp.ofp_type_map.get(msg.type, "unknown (%d)" % msg.type)
+ self.logger.debug("Checking packets[%d] %s) against %s", i, msg_str, exp_msg_str)
if msg.type == exp_msg:
(msg, pkt) = self.packets.pop(i)
return (msg, pkt)
diff --git a/src/python/oftest/oft12/packet.py b/src/python/oftest/oft12/packet.py
index 23a3e6e..a7aef94 100644
--- a/src/python/oftest/oft12/packet.py
+++ b/src/python/oftest/oft12/packet.py
@@ -36,12 +36,11 @@
import socket
import struct
import logging
-import oftest.cstruct as ofp
+import ofp
import unittest
import binascii
import string
import collections #@UnresolvedImport
-import oftest.action as action
ETHERTYPE_IP = 0x0800
ETHERTYPE_VLAN = 0x8100
diff --git a/src/python/oftest/oft12/testutils.py b/src/python/oftest/oft12/testutils.py
index e508be1..d6dbdf0 100644
--- a/src/python/oftest/oft12/testutils.py
+++ b/src/python/oftest/oft12/testutils.py
@@ -4,12 +4,8 @@
from cStringIO import StringIO
#import types
-import of12.cstruct as ofp
-import of12.match as oxm_field
-import of12.message as message
-import of12.action as action
-import of12.parse as parse
-import of12.instruction as instruction
+import ofp
+import oftest.parse as parse
from packet import Packet
try:
@@ -55,7 +51,7 @@
@param ctrl The controller object for the test
"""
logger.info("Initializing all table configs")
- request = message.table_mod()
+ request = ofp.message.table_mod()
request.config = ofp.OFPTC_TABLE_MISS_CONTROLLER
rv = 0
for table_id in [0, 1, 2, 3, 4, 5, 6, 7]:
@@ -82,10 +78,9 @@
@param table_id Table ID
"""
logger.info("Deleting all flows on table ID: " + str(table_id))
- msg = message.flow_mod()
+ msg = ofp.message.flow_delete()
msg.out_port = ofp.OFPP_ANY
msg.out_group = ofp.OFPG_ANY
- msg.command = ofp.OFPFC_DELETE
msg.buffer_id = 0xffffffff
msg.table_id = table_id
logger.debug(msg.show())
@@ -100,7 +95,7 @@
"""
logger.info("Deleting all groups")
- msg = message.group_mod()
+ msg = ofp.message.group_mod()
msg.group_id = ofp.OFPG_ALL
msg.command = ofp.OFPGC_DELETE
logger.debug(msg.show())
@@ -357,7 +352,7 @@
def do_barrier(ctrl):
- b = message.barrier_request()
+ b = ofp.message.barrier_request()
ctrl.transact(b)
@@ -371,7 +366,7 @@
@returns (hwaddr, config, advert) The hwaddress, configuration and
advertised values
"""
- request = message.features_request()
+ request = ofp.message.features_request()
reply, _ = controller.transact(request, timeout=2)
if reply is None:
logger.warn("Get feature request failed")
@@ -393,7 +388,7 @@
configuration value according to config and mask
"""
logger.info("Setting port " + str(port_no) + " to config " + str(config))
- request = message.features_request()
+ request = ofp.message.features_request()
reply, _ = controller.transact(request, timeout=2)
if reply is None:
return -1
@@ -403,7 +398,7 @@
break
if idx >= len(reply.ports):
return -1
- mod = message.port_mod()
+ mod = ofp.message.port_mod()
mod.port_no = port_no
mod.hw_addr = reply.ports[idx].hw_addr
mod.config = config
@@ -491,7 +486,7 @@
"""
(response, _) = parent.controller.poll(ofp.OFPT_PACKET_IN, 2)
- parent.assertTrue(response is not None, 'Packet in message not received')
+ parent.assertTrue(response is not None, 'Packet in ofp.message not received')
if str(exp_pkt) != response.data:
logging.debug("pkt len " + str(len(str(exp_pkt))) + ": "
+ str(exp_pkt).encode('hex'))
@@ -567,7 +562,7 @@
@param byte_count If >= 0, verify byte count
"""
(response, _) = parent.controller.poll(ofp.OFPT_FLOW_REMOVED, 2)
- parent.assertTrue(response is not None, 'No flow removed message received')
+ parent.assertTrue(response is not None, 'No flow removed ofp.message received')
if request is None:
return
@@ -608,24 +603,24 @@
See flow_match_test for other parameter descriptoins
if egr_queue is set
- append an out_queue action to egr_queue to the actions_list
+ append an out_queue ofp.action to egr_queue to the actions_list
else if egr_port is set:
- append an output action to egr_port to the actions_list
+ append an output ofp.action to egr_port to the actions_list
if the instruction_list is empty,
- append an APPLY instruction to it
- Add the action_list to the first write or apply instruction
+ append an APPLY ofp.instruction to it
+ Add the action_list to the first write or apply ofp.instruction
- @param egr_queue if not None, make the output an enqueue action
+ @param egr_queue if not None, make the output an enqueue ofp.action
@param table_id Table ID for writing a flow_mod
"""
if match_fields is None:
match_fields = parse.packet_to_flow_match(pkt)
parent.assertTrue(match_fields is not None, "Flow match from pkt failed")
- in_port = oxm_field.in_port(ing_port)
- match_fields.add(in_port)
- request = message.flow_mod()
- request.match_fields = match_fields
+ in_port = ofp.oxm.in_port(ing_port)
+ match_fields.oxm_list.append(in_port)
+ request = ofp.message.flow_add()
+ request.match= match_fields
request.buffer_id = 0xffffffff
request.table_id = table_id
@@ -638,21 +633,21 @@
if instruction_list is None:
instruction_list = []
- # Set up output/enqueue action if directed
+ # Set up output/enqueue ofp.action if directed
if egr_queue is not None:
parent.assertTrue(egr_port is not None, "Egress port not set")
- act = action.set_queue()
+ act = ofp.action.set_queue()
act.port = egr_port
act.queue_id = egr_queue
action_list.append(act)
elif egr_port is not None:
- act = action.output()
+ act = ofp.action.output()
act.port = egr_port
action_list.append(act)
inst = None
if len(instruction_list) == 0:
- inst = instruction.instruction_apply_actions()
+ inst = ofp.instruction.apply_actions()
instruction_list.append(inst)
else:
for inst in instruction_list:
@@ -660,26 +655,19 @@
inst.type == ofp.OFPIT_APPLY_ACTIONS):
break
+
# add all the actions to the last inst
- for act in action_list:
- logging.debug("Adding action " + act.show())
- rv = inst.actions.add(act)
- parent.assertTrue(rv, "Could not add action" + act.show())
- # NOTE that the inst has already been added to the flow_mod
+ inst.actions += action_list
# add all the instrutions to the flow_mod
- for i in instruction_list:
- logging.debug("Adding instruction " + inst.show())
- rv = request.instructions.add(i)
- parent.assertTrue(rv, "Could not add instruction " + i.show())
-
+ request.instructions += instruction_list
logging.debug(request.show())
return request
def flow_msg_install(parent, request, clear_table=True):
"""
- Install a flow mod message in the switch
+ Install a flow mod ofp.message in the switch
@param parent Must implement controller, assertEqual, assertTrue
@param request The request, all set to go
@@ -712,18 +700,18 @@
@param exp_code Expected error code
"""
(response, raw) = parent.controller.poll(ofp.OFPT_ERROR, 2)
- parent.assertTrue(response is not None, 'No error message received')
+ parent.assertTrue(response is not None, 'No error ofp.message received')
if (exp_type is None) or (exp_code is None):
logging.debug("Parametrs are not sufficient")
return
parent.assertEqual(exp_type, response.type,
- 'Error message type mismatch: ' +
+ 'Error ofp.message type mismatch: ' +
str(exp_type) + " != " +
str(response.type))
parent.assertEqual(exp_code, response.code,
- 'Error message code mismatch: ' +
+ 'Error ofp.message code mismatch: ' +
str(exp_code) + " != " +
str(response.code))
@@ -797,7 +785,7 @@
@param dl_vlan If not -1, and pkt is None, create a pkt w/ VLAN tag
@param exp_pkt If not None, use this as the expected output pkt; els use pkt
@param action_list Additional actions to add to flow mod
- @param check_expire Check for flow expiration message
+ @param check_expire Check for flow expiration ofp.message
"""
of_ports = port_map.keys()
of_ports.sort()
@@ -881,7 +869,7 @@
exp_pkt = simple_tcp_packet(
vlan_tags=[{'type': exp_vlan_type, 'vid': exp_vid, 'pcp': exp_pcp}])
else:
- #subtract action
+ #subtract ofp.action
if dl_vlan_int >= 0:
exp_pkt = simple_tcp_packet(
vlan_tags=[{'vid': dl_vlan_int, 'pcp': dl_vlan_pcp_int}])
@@ -919,7 +907,7 @@
elif exp_msg is ofp.OFPT_ERROR:
error_verify(parent, exp_msg_type, exp_msg_code)
else:
- parent.assertTrue(0, "Rcv: Unexpected Message: " + str(exp_msg))
+ parent.assertTrue(0, "Rcv: Unexpected ofp.message: " + str(exp_msg))
(_, rcv_pkt, _) = parent.dataplane.poll(timeout=1)
parent.assertFalse(rcv_pkt is not None, "Packet on dataplane")
@@ -958,13 +946,13 @@
@param match_exp Set whether packet is expected to receive
@param add_tag_exp If True, expected_packet has an additional vlan tag,
If not, expected_packet's vlan tag is replaced as specified
- @param exp_msg Expected message
- @param exp_msg_type Expected message type associated with the message
- @param exp_msg_code Expected message code associated with the msg_type
+ @param exp_msg Expected ofp.message
+ @param exp_msg_type Expected ofp.message type associated with the ofp.message
+ @param exp_msg_code Expected ofp.message code associated with the msg_type
@param pkt If not None, use this packet for ingress
@param exp_pkt If not None, use this as the expected output pkt
@param action_list Additional actions to add to flow mod
- @param check_expire Check for flow expiration message
+ @param check_expire Check for flow expiration ofp.message
"""
of_ports = port_map.keys()
of_ports.sort()
@@ -1029,7 +1017,7 @@
def action_generate(parent, field_to_mod, mod_field_vals):
"""
- Create an action to modify the field indicated in field_to_mod
+ Create an ofp.action to modify the field indicated in field_to_mod
@param parent Must implement, assertTrue
@param field_to_mod The field to modify as a string name
@@ -1042,41 +1030,41 @@
return None
if field_to_mod == 'dl_dst':
- act = action.set_dl_dst()
+ act = ofp.action.set_dl_dst()
act.dl_addr = parse.parse_mac(mod_field_vals['dl_dst'])
elif field_to_mod == 'dl_src':
- act = action.set_dl_src()
+ act = ofp.action.set_dl_src()
act.dl_addr = parse.parse_mac(mod_field_vals['dl_src'])
elif field_to_mod == 'vlan_tags':
if len(mod_field_vals['vlan_tags']):
- act = action.pop_vlan()
+ act = ofp.action.pop_vlan()
else:
pass
# elif field_to_mod == 'dl_vlan_enable':
# if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
-# act = action.pop_vlan()
+# act = ofp.action.pop_vlan()
# # Add VLAN tag is handled by dl_vlan field
# # Will return None in this case
# elif field_to_mod == 'dl_vlan':
-# act = action.set_vlan_vid()
+# act = ofp.action.set_vlan_vid()
# act.vlan_vid = mod_field_vals['dl_vlan']
# elif field_to_mod == 'dl_vlan_pcp':
-# act = action.set_vlan_pcp()
+# act = ofp.action.set_vlan_pcp()
# act.vlan_pcp = mod_field_vals['dl_vlan_pcp']
elif field_to_mod == 'ip_src':
- act = action.set_nw_src()
+ act = ofp.action.set_nw_src()
act.nw_addr = parse.parse_ip(mod_field_vals['ip_src'])
elif field_to_mod == 'ip_dst':
- act = action.set_nw_dst()
+ act = ofp.action.set_nw_dst()
act.nw_addr = parse.parse_ip(mod_field_vals['ip_dst'])
elif field_to_mod == 'ip_tos':
- act = action.set_nw_tos()
+ act = ofp.action.set_nw_tos()
act.nw_tos = mod_field_vals['ip_tos']
elif field_to_mod == 'tcp_sport':
- act = action.set_tp_src()
+ act = ofp.action.set_tp_src()
act.tp_port = mod_field_vals['tcp_sport']
elif field_to_mod == 'tcp_dport':
- act = action.set_tp_dst()
+ act = ofp.action.set_tp_dst()
act.tp_port = mod_field_vals['tcp_dport']
else:
parent.assertTrue(0, "Unknown field to modify: " + str(field_to_mod))
@@ -1086,7 +1074,7 @@
def pkt_action_setup(parent, start_field_vals={}, mod_field_vals={},
mod_fields={}, check_test_params=False):
"""
- Set up the ingress and expected packet and action list for a test
+ Set up the ingress and expected packet and ofp.action list for a test
@param parent Must implement, assertTrue, config hash and logger
@param start_field_values Field values to use for ingress packet (optional)
@@ -1095,7 +1083,7 @@
@params check_test_params If True, will check the parameters vid, add_vlan
and strip_vlan from the command line.
- Returns a triple: pkt-to-send, expected-pkt, action-list
+ Returns a triple: pkt-to-send, expected-pkt, ofp.action-list
"""
new_actions = []
@@ -1184,7 +1172,7 @@
def skip_message_emit(parent, s):
"""
- Print out a 'skipped' message to stderr
+ Print out a 'skipped' ofp.message to stderr
@param s The string to print out to the log file
@param parent Must implement config and logger objects
@@ -1199,11 +1187,11 @@
sys.stderr.write("(S)")
def do_echo_request_reply_test(test,controller):
- request = message.echo_request()
+ request = ofp.message.echo_request()
response, _ = controller.transact(request)
- test.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,
+ test.assertEqual(response.type, ofp.OFPT_ECHO_REPLY,
'response is not echo_reply')
- test.assertEqual(request.header.xid, response.header.xid,
+ test.assertEqual(request.xid, response.xid,
'response xid != request xid')
test.assertEqual(len(response.data), 0, 'response data non-empty')
@@ -1399,7 +1387,7 @@
elif exp_msg == ofp.OFPT_ERROR:
error_verify(parent, exp_msg_type, exp_msg_code)
else:
- parent.assertTrue(0, "Rcv: Unexpected Message: " + str(exp_msg))
+ parent.assertTrue(0, "Rcv: Unexpected ofp.message: " + str(exp_msg))
(_, rcv_pkt, _) = parent.dataplane.poll(timeout=1)
parent.assertFalse(rcv_pkt is not None, "Packet on dataplane")
@@ -1446,13 +1434,13 @@
@param match_exp Set whether packet is expected to receive
@param add_tag_exp If True, expected_packet has an additional MPLS shim,
If not expected_packet's MPLS shim is replaced as specified
- @param exp_msg Expected message
- @param exp_msg_type Expected message type associated with the message
- @param exp_msg_code Expected message code associated with the msg_type
+ @param exp_msg Expected ofp.message
+ @param exp_msg_type Expected ofp.message type associated with the ofp.message
+ @param exp_msg_code Expected ofp.message code associated with the msg_type
@param pkt If not None, use this packet for ingress
@param exp_pkt If not None, use this as the expected output pkt; els use pkt
@param action_list Additional actions to add to flow mod
- @param check_expire Check for flow expiration message
+ @param check_expire Check for flow expiration ofp.message
"""
of_ports = port_map.keys()
of_ports.sort()
@@ -1501,7 +1489,7 @@
""" Get the flow_stats from the switch
Test the response to make sure it's really a flow_stats object
"""
- request = message.flow_stats_request()
+ request = ofp.message.flow_stats_request()
request.out_port = ofp.OFPP_ANY
request.out_group = ofp.OFPG_ANY
request.table_id = 0xff
@@ -1509,6 +1497,6 @@
request.match_fields = match_fields
response, _ = parent.controller.transact(request, timeout=2)
parent.assertTrue(response is not None, "Did not get response")
- parent.assertTrue(isinstance(response,message.flow_stats_reply),
+ parent.assertTrue(isinstance(response,ofp.message.flow_stats_reply),
"Expected a flow_stats_reply, but didn't get it")
return response
diff --git a/src/python/oftest/parse.py b/src/python/oftest/parse.py
index d75c7cd..8c98c91 100644
--- a/src/python/oftest/parse.py
+++ b/src/python/oftest/parse.py
@@ -3,8 +3,7 @@
"""
import sys
-import logging
-import ofp
+import socket
try:
import scapy.all as scapy
except:
@@ -13,27 +12,6 @@
except:
sys.exit("Need to install scapy for packet parsing")
-map_wc_field_to_match_member = {
- 'OFPFW_DL_VLAN' : 'vlan_vid',
- 'OFPFW_DL_SRC' : 'eth_src',
- 'OFPFW_DL_DST' : 'eth_dst',
- 'OFPFW_DL_TYPE' : 'eth_type',
- 'OFPFW_NW_PROTO' : 'ip_proto',
- 'OFPFW_TP_SRC' : 'tcp_src',
- 'OFPFW_TP_DST' : 'tcp_dst',
- 'OFPFW_NW_SRC_SHIFT' : 'nw_src_shift',
- 'OFPFW_NW_SRC_BITS' : 'nw_src_bits',
- 'OFPFW_NW_SRC_MASK' : 'nw_src_mask',
- 'OFPFW_NW_SRC_ALL' : 'nw_src_all',
- 'OFPFW_NW_DST_SHIFT' : 'nw_dst_shift',
- 'OFPFW_NW_DST_BITS' : 'nw_dst_bits',
- 'OFPFW_NW_DST_MASK' : 'nw_dst_mask',
- 'OFPFW_NW_DST_ALL' : 'nw_dst_all',
- 'OFPFW_DL_VLAN_PCP' : 'vlan_pcp',
- 'OFPFW_NW_TOS' : 'ip_dscp'
-}
-
-
def parse_mac(mac_str):
"""
Parse a MAC address
@@ -61,6 +39,14 @@
val += a
return val
+def parse_ipv6(ip_str):
+ """
+ Parse an IPv6 address
+
+ Parse a textual IPv6 address and return a 16 byte binary string.
+ """
+ return socket.inet_pton(socket.AF_INET6, ip_str)
+
def packet_type_classify(ether):
try:
dot1q = ether[scapy.Dot1Q]
@@ -93,26 +79,30 @@
arp = None
return (dot1q, ip, tcp, udp, icmp, arp)
-def packet_to_flow_match(packet, pkt_format="L2"):
+def packet_to_flow_match(packet):
"""
Create a flow match that matches packet with the given wildcards
@param packet The packet to use as a flow template
- @param pkt_format Currently only L2 is supported. Will indicate the
- overall packet type for parsing
- @return An ofp_match object if successful. None if format is not
- recognized. The wildcards of the match will be cleared for the
- values extracted from the packet.
+ @return An loxi.of10.match object
@todo check min length of packet
- @todo Check if packet is other than L2 format
- @todo Implement ICMP and ARP fields
"""
+ import ofp
+ if ofp.OFP_VERSION == 1:
+ return packet_to_flow_match_v1(packet)
+ elif ofp.OFP_VERSION == 3:
+ return packet_to_flow_match_v3(packet)
+ elif ofp.OFP_VERSION == 4:
+ return packet_to_flow_match_v4(packet)
+ else:
+ raise NotImplementedError()
- #@todo check min length of packet
- if pkt_format.upper() != "L2":
- logging.error("Only L2 supported for packet_to_flow")
- return None
+def packet_to_flow_match_v1(packet):
+ """
+ OpenFlow 1.0 implementation of packet_to_flow_match
+ """
+ import loxi.of10 as ofp
if type(packet) == type(""):
ether = scapy.Ether(packet)
@@ -123,8 +113,7 @@
try:
(dot1q, ip, tcp, udp, icmp, arp) = packet_type_classify(ether)
except:
- logging.error("packet_to_flow_match: Classify error")
- return None
+ raise ValueError("could not classify packet")
match = ofp.match()
match.wildcards = ofp.OFPFW_ALL
@@ -183,3 +172,111 @@
match.wildcards &= ~ofp.OFPFW_NW_DST_MASK
return match
+
+def packet_to_flow_match_v3(packet):
+ """
+ OpenFlow 1.2 implementation of packet_to_flow_match
+ """
+ import loxi.of12 as ofp
+ return packet_to_flow_match_oxm(packet, ofp)
+
+def packet_to_flow_match_v4(packet):
+ """
+ OpenFlow 1.3 implementation of packet_to_flow_match
+ """
+ import loxi.of13 as ofp
+ return packet_to_flow_match_oxm(packet, ofp)
+
+def packet_to_flow_match_oxm(packet, ofp):
+ def parse_ether_layer(layer, match):
+ assert(type(layer) == scapy.Ether)
+ match.oxm_list.append(ofp.oxm.eth_dst(parse_mac(layer.dst)))
+ match.oxm_list.append(ofp.oxm.eth_src(parse_mac(layer.src)))
+
+ if type(layer.payload) == scapy.Dot1Q:
+ layer = layer.payload
+ match.oxm_list.append(ofp.oxm.eth_type(layer.type))
+ match.oxm_list.append(ofp.oxm.vlan_vid(layer.vlan))
+ match.oxm_list.append(ofp.oxm.vlan_pcp(layer.prio))
+ else:
+ match.oxm_list.append(ofp.oxm.eth_type(layer.type))
+ match.oxm_list.append(ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE))
+
+ if type(layer.payload) == scapy.IP:
+ parse_ipv4_layer(layer.payload, match)
+ elif type(layer.payload) == scapy.IPv6:
+ parse_ipv6_layer(layer.payload, match)
+ elif type(layer.payload) == scapy.ARP:
+ parse_arp_layer(layer.payload, match)
+ # TODO MPLS
+
+ def parse_ipv4_layer(layer, match):
+ assert(type(layer) == scapy.IP)
+ match.oxm_list.append(ofp.oxm.ip_proto(layer.proto))
+ match.oxm_list.append(ofp.oxm.ip_dscp(layer.tos >> 2))
+ match.oxm_list.append(ofp.oxm.ip_ecn(layer.tos & 3))
+ match.oxm_list.append(ofp.oxm.ipv4_src(parse_ip(layer.src)))
+ match.oxm_list.append(ofp.oxm.ipv4_dst(parse_ip(layer.dst)))
+
+ if type(layer.payload) == scapy.TCP:
+ parse_tcp_layer(layer.payload, match)
+ elif type(layer.payload) == scapy.UDP:
+ parse_udp_layer(layer.payload, match)
+ elif type(layer.payload) == scapy.ICMP:
+ parse_icmpv4_layer(layer.payload, match)
+ # TODO SCTP
+
+ def parse_tcp_layer(layer, match):
+ assert(type(layer) == scapy.TCP)
+ match.oxm_list.append(ofp.oxm.tcp_src(layer.sport))
+ match.oxm_list.append(ofp.oxm.tcp_dst(layer.dport))
+
+ def parse_udp_layer(layer, match):
+ assert(type(layer) == scapy.UDP)
+ match.oxm_list.append(ofp.oxm.udp_src(layer.sport))
+ match.oxm_list.append(ofp.oxm.udp_dst(layer.dport))
+
+ def parse_icmpv4_layer(layer, match):
+ assert(type(layer) == scapy.ICMP)
+ match.oxm_list.append(ofp.oxm.icmpv4_type(layer.type))
+ match.oxm_list.append(ofp.oxm.icmpv4_code(layer.code))
+
+ def parse_arp_layer(layer, match):
+ assert(type(layer) == scapy.ARP)
+ match.oxm_list.append(ofp.oxm.arp_op(layer.op))
+ match.oxm_list.append(ofp.oxm.arp_spa(parse_ip(layer.psrc)))
+ match.oxm_list.append(ofp.oxm.arp_tpa(parse_ip(layer.pdst)))
+ match.oxm_list.append(ofp.oxm.arp_sha(parse_mac(layer.hwsrc)))
+ match.oxm_list.append(ofp.oxm.arp_tha(parse_mac(layer.hwdst)))
+
+ def parse_ipv6_layer(layer, match):
+ assert(type(layer) == scapy.IPv6)
+ # TODO handle chained headers
+ match.oxm_list.append(ofp.oxm.ip_proto(layer.nh))
+ match.oxm_list.append(ofp.oxm.ip_dscp(layer.tc >> 2))
+ match.oxm_list.append(ofp.oxm.ip_ecn(layer.tc & 3))
+ match.oxm_list.append(ofp.oxm.ipv6_src(parse_ipv6(layer.src)))
+ match.oxm_list.append(ofp.oxm.ipv6_dst(parse_ipv6(layer.dst)))
+ match.oxm_list.append(ofp.oxm.ipv6_flabel(layer.fl))
+
+ if type(layer.payload) == scapy.TCP:
+ parse_tcp_layer(layer.payload, match)
+ elif type(layer.payload) == scapy.UDP:
+ parse_udp_layer(layer.payload, match)
+ elif layer.nh == 0x3a:
+ parse_icmpv6_layer(layer.payload, match)
+ # TODO ND
+ # TODO SCTP
+
+ def parse_icmpv6_layer(layer, match):
+ match.oxm_list.append(ofp.oxm.icmpv6_type(layer.type))
+ match.oxm_list.append(ofp.oxm.icmpv6_code(layer.code))
+
+ if type(packet) == type(""):
+ ether = scapy.Ether(packet)
+ else:
+ ether = packet
+
+ match = ofp.match()
+ parse_ether_layer(packet, match)
+ return match
diff --git a/src/python/oftest/test_parse.py b/src/python/oftest/test_parse.py
new file mode 100755
index 0000000..7143350
--- /dev/null
+++ b/src/python/oftest/test_parse.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+import unittest
+import parse
+import scapy.all as scapy
+
+class TestPacketToFlowMatchV3(unittest.TestCase):
+ def test_tcp(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.IP(src='192.168.0.1', dst='192.168.0.2', tos=2 | (32 << 2), ttl=64)/ \
+ scapy.TCP(sport=1234, dport=80)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x0800),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ofp.oxm.ip_proto(6),
+ ofp.oxm.ip_dscp(32),
+ ofp.oxm.ip_ecn(2),
+ ofp.oxm.ipv4_src(0xc0a80001),
+ ofp.oxm.ipv4_dst(0xc0a80002),
+ ofp.oxm.tcp_src(1234),
+ ofp.oxm.tcp_dst(80)
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_udp(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.IP(src='192.168.0.1', dst='192.168.0.2', tos=2 | (32 << 2), ttl=64)/ \
+ scapy.UDP(sport=1234, dport=80)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x0800),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ofp.oxm.ip_proto(17),
+ ofp.oxm.ip_dscp(32),
+ ofp.oxm.ip_ecn(2),
+ ofp.oxm.ipv4_src(0xc0a80001),
+ ofp.oxm.ipv4_dst(0xc0a80002),
+ ofp.oxm.udp_src(1234),
+ ofp.oxm.udp_dst(80)
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_icmp(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.IP(src='192.168.0.1', dst='192.168.0.2', tos=2 | (32 << 2), ttl=64)/ \
+ scapy.ICMP(type=8, code=1)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x0800),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ofp.oxm.ip_proto(1),
+ ofp.oxm.ip_dscp(32),
+ ofp.oxm.ip_ecn(2),
+ ofp.oxm.ipv4_src(0xc0a80001),
+ ofp.oxm.ipv4_dst(0xc0a80002),
+ ofp.oxm.icmpv4_type(8),
+ ofp.oxm.icmpv4_code(1)
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_arp(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.ARP(hwsrc='00:01:02:03:04:05', hwdst='00:06:07:08:09:0a', \
+ psrc='192.168.0.1', pdst='192.168.0.2', op=1)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x0806),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ofp.oxm.arp_op(1),
+ ofp.oxm.arp_spa(0xc0a80001),
+ ofp.oxm.arp_tpa(0xc0a80002),
+ ofp.oxm.arp_sha([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.arp_tha([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_tcpv6(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.IPv6(src="::1", dst="::2", nh=6, tc=2 | (32 << 2), fl=7)/ \
+ scapy.TCP(sport=1234, dport=80)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x86dd),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ofp.oxm.ip_proto(6),
+ ofp.oxm.ip_dscp(32),
+ ofp.oxm.ip_ecn(2),
+ ofp.oxm.ipv6_src("\x00" * 15 + "\x01"),
+ ofp.oxm.ipv6_dst("\x00" * 15 + "\x02"),
+ ofp.oxm.ipv6_flabel(7),
+ ofp.oxm.tcp_src(1234),
+ ofp.oxm.tcp_dst(80)
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_icmpv6(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.IPv6(src="::1", dst="::2", tc=2 | (32 << 2), fl=7)/ \
+ scapy.ICMPv6EchoRequest()
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x86dd),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ofp.oxm.ip_proto(0x3a),
+ ofp.oxm.ip_dscp(32),
+ ofp.oxm.ip_ecn(2),
+ ofp.oxm.ipv6_src("\x00" * 15 + "\x01"),
+ ofp.oxm.ipv6_dst("\x00" * 15 + "\x02"),
+ ofp.oxm.ipv6_flabel(7),
+ ofp.oxm.icmpv6_type(128),
+ ofp.oxm.icmpv6_code(0)
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_vlan(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a')/ \
+ scapy.Dot1Q(vlan=50, prio=5)/ \
+ scapy.IP(src='192.168.0.1', dst='192.168.0.2', tos=2 | (32 << 2), ttl=64)/ \
+ scapy.TCP(sport=1234, dport=80)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x0800),
+ ofp.oxm.vlan_vid(50),
+ ofp.oxm.vlan_pcp(5),
+ ofp.oxm.ip_proto(6),
+ ofp.oxm.ip_dscp(32),
+ ofp.oxm.ip_ecn(2),
+ ofp.oxm.ipv4_src(0xc0a80001),
+ ofp.oxm.ipv4_dst(0xc0a80002),
+ ofp.oxm.tcp_src(1234),
+ ofp.oxm.tcp_dst(80)
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+ def test_unknown_ethertype(self):
+ import loxi.of12 as ofp
+ self.maxDiff = None
+ pkt = scapy.Ether(dst='00:01:02:03:04:05', src='00:06:07:08:09:0a', type=0x0801)/ \
+ ('\x11' * 20)
+ expected = [
+ ofp.oxm.eth_dst([0x00, 0x01, 0x02, 0x03, 0x04, 0x05]),
+ ofp.oxm.eth_src([0x00, 0x06, 0x07, 0x08, 0x09, 0x0a]),
+ ofp.oxm.eth_type(0x0801),
+ ofp.oxm.vlan_vid(ofp.OFP_VLAN_NONE),
+ ]
+ result = parse.packet_to_flow_match_v3(pkt).oxm_list
+ self.assertEquals([x.show() for x in expected], [x.show() for x in result])
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/tests-1.2/basic.py b/tests-1.2/basic.py
index 76a5a16..fe45502 100644
--- a/tests-1.2/basic.py
+++ b/tests-1.2/basic.py
@@ -28,9 +28,9 @@
request = ofp.message.echo_request()
request.data = 'OpenFlow Will Rule The World'
response, _ = self.controller.transact(request)
- self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,
+ self.assertEqual(response.type, ofp.OFPT_ECHO_REPLY,
'response is not echo_reply')
- self.assertEqual(request.header.xid, response.header.xid,
+ self.assertEqual(request.xid, response.xid,
'response xid != request xid')
self.assertEqual(request.data, response.data,
'response data does not match request')
@@ -45,9 +45,8 @@
request = ofp.message.features_request()
response,_ = self.controller.transact(request)
self.assertTrue(response,"Got no features_reply to features_request")
- self.assertEqual(response.header.type, ofp.OFPT_FEATURES_REPLY,
- 'response is not echo_reply')
- self.assertTrue(len(response) >= 32, "features_reply too short: %d < 32 " % len(response))
+ self.assertEqual(response.type, ofp.OFPT_FEATURES_REPLY,
+ 'response is not features_reply')
class PacketIn(base_tests.SimpleDataPlane):
"""
@@ -69,7 +68,7 @@
pkt = testutils.simple_tcp_packet()
self.dataplane.send(of_port, str(pkt))
#@todo Check for unexpected messages?
- (response, _) = self.controller.poll(ofp.OFPT_PACKET_IN, 2)
+ (response, _) = self.controller.poll(ofp.OFPT_PACKET_IN)
self.assertTrue(response is not None,
'Packet in message not received on port ' +
@@ -107,10 +106,11 @@
for dp_port in of_ports:
msg = ofp.message.packet_out()
msg.in_port = ofp.OFPP_CONTROLLER
+ msg.buffer_id = 0xffffffff
msg.data = str(outpkt)
act = ofp.action.output()
act.port = dp_port
- self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
+ msg.actions.append(act)
logging.info("PacketOut to: " + str(dp_port))
rv = self.controller.message_send(msg)
@@ -137,7 +137,7 @@
def runTest(self):
logging.info("Running StatsGet")
logging.info("Inserting trial flow")
- request = ofp.message.flow_mod()
+ request = ofp.message.flow_add()
request.buffer_id = 0xffffffff
for i in range(1,5):
request.priority = i*1000
@@ -154,7 +154,7 @@
response, _ = self.controller.transact(request, timeout=2)
self.assertTrue(response is not None, "Did not get response")
self.assertTrue(isinstance(response,ofp.message.flow_stats_reply),"Not a flow_stats_reply")
- self.assertEqual(len(response.stats),0)
+ self.assertEqual(len(response.entries),0)
logging.debug(response.show())
@@ -168,7 +168,7 @@
def runTest(self):
logging.info("Running StatsGet")
logging.info("Inserting trial flow")
- request = ofp.message.flow_mod()
+ request = ofp.message.flow_add()
request.buffer_id = 0xffffffff
rv = self.controller.message_send(request)
self.assertTrue(rv != -1, "Failed to insert test flow")
@@ -201,7 +201,7 @@
def runTest(self):
logging.info("Running " + str(self))
- request = ofp.message.flow_mod()
+ request = ofp.message.flow_add()
request.buffer_id = 0xffffffff
rv = self.controller.message_send(request)
self.assertTrue(rv != -1, "Error installing flow mod")
diff --git a/tests-1.2/flow_mods.py b/tests-1.2/flow_mods.py
index 1fe05ee..27ebb9e 100644
--- a/tests-1.2/flow_mods.py
+++ b/tests-1.2/flow_mods.py
@@ -39,11 +39,16 @@
testutils.do_barrier(self.controller)
self.assertEqual(rv, 0, "Failed to insert 2nd flow_mod")
flow_stats = testutils.flow_stats_get(self)
- self.assertEqual(len(flow_stats.stats),1,
+ self.assertEqual(len(flow_stats.entries),1,
"Expected only one flow_mod")
- stat = flow_stats.stats[0]
+ stat = flow_stats.entries[0]
+
+ def canonicalize_match(match):
+ match.oxm_list.sort(key=lambda x: x.type_len)
+
+ canonicalize_match(stat.match)
+ canonicalize_match(fm_new.match)
self.assertEqual(stat.match, fm_new.match)
- self.assertEqual(stat.match_fields, fm_new.match_fields)
self.assertEqual(stat.instructions, fm_new.instructions)
# @todo consider adding more tests here
diff --git a/tests-1.2/groups.py b/tests-1.2/groups.py
index 76948db..0b417e2 100644
--- a/tests-1.2/groups.py
+++ b/tests-1.2/groups.py
@@ -4,9 +4,10 @@
import logging
from oftest import config
-import of12 as ofp
+import ofp
import oftest.oft12.testutils as testutils
import oftest.base_tests as base_tests
+import oftest.parse
def create_group_desc_stats_req():
# XXX Zoltan: hack, remove if message module is fixed
@@ -28,10 +29,10 @@
group_id = 0, buckets = []):
m = ofp.message.group_mod()
m.command = command
- m.type = type
+ m.group_type = type
m.group_id = group_id
for b in buckets:
- m.buckets.add(b)
+ m.buckets.append(b)
return m
@@ -39,12 +40,12 @@
# XXX Zoltan: watch_port/_group off ?
def create_bucket(weight = 0, watch_port = 0, watch_group = 0, actions=[]):
- b = ofp.bucket.bucket()
+ b = ofp.bucket()
b.weight = weight
b.watch_port = watch_port
b.watch_group = watch_group
for a in actions:
- b.actions.add(a)
+ b.actions.append(a)
return b
@@ -62,36 +63,35 @@
return act
if a == ofp.OFPAT_SET_FIELD:
port = kwargs.get('tcp_sport', 0)
- field_2b_set = ofp.match.tcp_src(port)
+ field_2b_set = ofp.oxm.tcp_src(port)
act = ofp.action.set_field()
- act.field = field_2b_set
+ act.field = field_2b_set.pack() + '\x00' * 6 # HACK
return act;
def create_flow_msg(packet = None, in_port = None, match = None, apply_action_list = []):
- apply_inst = ofp.instruction.instruction_apply_actions()
+ apply_inst = ofp.instruction.apply_actions()
if apply_action_list is not None:
for act in apply_action_list:
- apply_inst.actions.add(act)
+ apply_inst.actions.append(act)
- request = ofp.message.flow_mod()
- request.match.type = ofp.OFPMT_OXM
+ request = ofp.message.flow_add()
if match is None:
- match = ofp.parse.packet_to_flow_match(packet)
+ match = oftest.parse.packet_to_flow_match(packet)
- request.match_fields = match
+ request.match = match
if in_port != None:
- match_port = testutils.oxm_field.in_port(in_port)
- request.match_fields.tlvs.append(match_port)
+ match_port = ofp.oxm.in_port(in_port)
+ request.match.oxm_list.append(match_port)
request.buffer_id = 0xffffffff
request.priority = 1000
- request.instructions.add(apply_inst)
+ request.instructions.append(apply_inst)
return request
@@ -130,11 +130,11 @@
self.assertTrue(response is not None,
'Did not receive an error message')
- self.assertEqual(response.header.type, ofp.OFPT_ERROR,
+ self.assertEqual(response.type, ofp.OFPT_ERROR,
'Did not receive an error message')
if type != 0:
- self.assertEqual(response.type, type,
+ self.assertEqual(response.err_type, type,
'Did not receive a ' + str(type) + ' type error message')
if code != 0:
@@ -1024,16 +1024,14 @@
self.send_ctrl_exp_reply(group_stats_req,
ofp.OFPT_STATS_REPLY, 'group stat')
- exp_len = ofp.OFP_HEADER_BYTES + \
- ofp.OFP_STATS_REPLY_BYTES + \
- ofp.OFP_GROUP_STATS_BYTES + \
- ofp.OFP_BUCKET_COUNTER_BYTES * 2
+ self.assertEqual(len(response.entries), 1, 'Incorrect number of groups')
+ self.assertEqual(len(response.entries[0].bucket_stats), 2, 'Incorrect number of groups')
+ self.assertEqual(response.entries[0].packet_count, 3, 'Incorrect group packet count')
+ self.assertEqual(response.entries[0].byte_count, 300, 'Incorrect group byte count')
+ for bucket_stat in response.entries[0].bucket_stats:
+ self.assertEqual(bucket_stat.packet_count, 3, 'Incorrect bucket packet count')
+ self.assertEqual(bucket_stat.byte_count, 300, 'Incorrect bucket byte count')
- self.assertEqual(len(response), exp_len,
- 'Received packet length does not equal expected length')
- # XXX Zoltan: oftest group_stats_req handling needs to be fixed
- # right now only the expected message length is checked
- # responses should be checked in Wireshark
@@ -1103,18 +1101,28 @@
self.send_ctrl_exp_reply(group_stats_req,
ofp.OFPT_STATS_REPLY, 'group stat')
- exp_len = ofp.OFP_HEADER_BYTES + \
- ofp.OFP_STATS_REPLY_BYTES + \
- ofp.OFP_GROUP_STATS_BYTES + \
- ofp.OFP_BUCKET_COUNTER_BYTES * 2 + \
- ofp.OFP_GROUP_STATS_BYTES + \
- ofp.OFP_BUCKET_COUNTER_BYTES * 2
+ self.assertEqual(len(response.entries), 2)
+ group10, group20 = sorted(response.entries, key=lambda x: x.group_id)
- self.assertEqual(len(response), exp_len,
- 'Received packet length does not equal expected length')
- # XXX Zoltan: oftest group_stats_req handling needs to be fixed
- # right now only the expected message length is checked
- # responses should be checked in Wireshark
+ # Check stats for group 10
+ self.assertEqual(group10.group_id, 10)
+ self.assertEqual(group10.ref_count, 1)
+ self.assertEqual(group10.packet_count, 2)
+ self.assertEqual(group10.byte_count, 200)
+ self.assertEqual(len(group10.bucket_stats), 2)
+ for bucket_stat in group10.bucket_stats:
+ self.assertEqual(bucket_stat.packet_count, 2)
+ self.assertEqual(bucket_stat.byte_count, 200)
+
+ # Check stats for group 20
+ self.assertEqual(group20.group_id, 20)
+ self.assertEqual(group20.ref_count, 1)
+ self.assertEqual(group20.packet_count, 3)
+ self.assertEqual(group20.byte_count, 300)
+ self.assertEqual(len(group20.bucket_stats), 2)
+ for bucket_stat in group20.bucket_stats:
+ self.assertEqual(bucket_stat.packet_count, 3)
+ self.assertEqual(bucket_stat.byte_count, 300)
@@ -1151,16 +1159,13 @@
self.send_ctrl_exp_reply(group_desc_stats_req,
ofp.OFPT_STATS_REPLY, 'group desc stat')
- exp_len = ofp.OFP_HEADER_BYTES + \
- ofp.OFP_STATS_REPLY_BYTES + \
- ofp.OFP_GROUP_DESC_STATS_BYTES + \
- len(b1) + len(b2) + len(b3)
-
- self.assertEqual(len(response), exp_len,
- 'Received packet length does not equal expected length')
- # XXX Zoltan: oftest group_stats_req handling needs to be fixed
- # right now only the expected message length is checked
- # responses should be checked in Wireshark
+ self.assertEquals(len(response.entries), 1)
+ group = response.entries[0]
+ self.assertEquals(group.group_id, 10)
+ self.assertEquals(len(group.buckets), 3)
+ self.assertEquals(group.buckets[0], b1)
+ self.assertEquals(group.buckets[1], b2)
+ self.assertEquals(group.buckets[2], b3)
#@todo: A flow added with group action should increase the ref counter of the ref. group
@@ -1246,7 +1251,7 @@
self.send_ctrl_exp_reply(aggr_stat_req,
ofp.OFPT_STATS_REPLY, 'aggr stat')
- self.assertEqual(response.stats[0].flow_count, 2,
+ self.assertEqual(response.flow_count, 2,
'Did not match expected flow count')
class GroupFlowSelectAll(GroupTest):
@@ -1315,7 +1320,7 @@
self.send_ctrl_exp_reply(aggr_stat_req,
ofp.OFPT_STATS_REPLY, 'group desc stat')
- self.assertEqual(response.stats[0].flow_count, 4,
+ self.assertEqual(response.flow_count, 4,
'Did not match expected flow count')
diff --git a/tests-1.2/ipv6.py b/tests-1.2/ipv6.py
index c871a6b..5a45e9d 100644
--- a/tests-1.2/ipv6.py
+++ b/tests-1.2/ipv6.py
@@ -19,6 +19,7 @@
import ofp
import oftest.oft12.testutils as testutils
import oftest.base_tests as base_tests
+import oftest.parse
TEST_VID_DEFAULT = 2
@@ -48,22 +49,21 @@
# Add entry match
- request = ofp.message.flow_mod()
- request.match.type = ofp.OFPMT_OXM
- port = ofp.match.in_port(of_ports[0])
- eth_type = ofp.match.eth_type(IPV6_ETHERTYPE)
- eth_dst = ofp.match.eth_dst(ofp.parse.parse_mac("00:01:02:03:04:05"))
- ipv6_src = ofp.match.ipv6_src(ipaddr.IPv6Address('fe80::2420:52ff:fe8f:5189'))
+ request = ofp.message.flow_add()
+ port = ofp.oxm.in_port(of_ports[0])
+ eth_type = ofp.oxm.eth_type(IPV6_ETHERTYPE)
+ eth_dst = ofp.oxm.eth_dst(oftest.parse.parse_mac("00:01:02:03:04:05"))
+ ipv6_src = ofp.oxm.ipv6_src(oftest.parse.parse_ipv6('fe80::2420:52ff:fe8f:5189'))
- request.match_fields.tlvs.append(port)
- request.match_fields.tlvs.append(eth_type)
- request.match_fields.tlvs.append(eth_dst)
- request.match_fields.tlvs.append(ipv6_src)
+ request.match.oxm_list.append(port)
+ request.match.oxm_list.append(eth_type)
+ request.match.oxm_list.append(eth_dst)
+ request.match.oxm_list.append(ipv6_src)
act = ofp.action.output()
act.port = of_ports[3]
- inst = ofp.instruction.instruction_apply_actions()
- inst.actions.add(act)
- request.instructions.add(inst)
+ inst = ofp.instruction.apply_actions()
+ inst.actions.append(act)
+ request.instructions.append(inst)
request.buffer_id = 0xffffffff
request.priority = 1000
@@ -103,25 +103,24 @@
# Add entry match
- request = ofp.message.flow_mod()
- request.match.type = ofp.OFPMT_OXM
- port = ofp.match.in_port(of_ports[0])
- eth_type = ofp.match.eth_type(IPV6_ETHERTYPE)
- ipv6_src = ofp.match.ipv6_src(ipaddr.IPv6Address('fe80::2420:52ff:fe8f:5189'))
- ip_proto = ofp.match.ip_proto(ICMPV6_PROTOCOL)
- icmpv6_type = ofp.match.icmpv6_type(128)
+ request = ofp.message.flow_add()
+ port = ofp.oxm.in_port(of_ports[0])
+ eth_type = ofp.oxm.eth_type(IPV6_ETHERTYPE)
+ ipv6_src = ofp.oxm.ipv6_src(oftest.parse.parse_ipv6('fe80::2420:52ff:fe8f:5189'))
+ ip_proto = ofp.oxm.ip_proto(ICMPV6_PROTOCOL)
+ icmpv6_type = ofp.oxm.icmpv6_type(128)
- request.match_fields.tlvs.append(port)
- request.match_fields.tlvs.append(eth_type)
- request.match_fields.tlvs.append(ipv6_src)
- request.match_fields.tlvs.append(ip_proto)
- request.match_fields.tlvs.append(icmpv6_type)
+ request.match.oxm_list.append(port)
+ request.match.oxm_list.append(eth_type)
+ request.match.oxm_list.append(ipv6_src)
+ request.match.oxm_list.append(ip_proto)
+ request.match.oxm_list.append(icmpv6_type)
act = ofp.action.output()
act.port = of_ports[3]
- inst = ofp.instruction.instruction_apply_actions()
- inst.actions.add(act)
- request.instructions.add(inst)
+ inst = ofp.instruction.apply_actions()
+ inst.actions.append(act)
+ request.instructions.append(inst)
request.buffer_id = 0xffffffff
request.priority = 1000
@@ -159,29 +158,28 @@
# Add entry match
- request = ofp.message.flow_mod()
- request.match.type = ofp.OFPMT_OXM
- port = ofp.match.in_port(of_ports[0])
- eth_type = ofp.match.eth_type(IPV6_ETHERTYPE)
- ipv6_src = ofp.match.ipv6_src(ipaddr.IPv6Address('fe80::2420:52ff:fe8f:5189'))
+ request = ofp.message.flow_add()
+ port = ofp.oxm.in_port(of_ports[0])
+ eth_type = ofp.oxm.eth_type(IPV6_ETHERTYPE)
+ ipv6_src = ofp.oxm.ipv6_src(oftest.parse.parse_ipv6('fe80::2420:52ff:fe8f:5189'))
- request.match_fields.tlvs.append(port)
- request.match_fields.tlvs.append(eth_type)
- request.match_fields.tlvs.append(ipv6_src)
+ request.match.oxm_list.append(port)
+ request.match.oxm_list.append(eth_type)
+ request.match.oxm_list.append(ipv6_src)
- field_2b_set = ofp.match.ipv6_dst(ipaddr.IPv6Address('fe80::2420:52ff:fe8f:DDDD'))
+ field_2b_set = ofp.oxm.ipv6_dst(oftest.parse.parse_ipv6('fe80::2420:52ff:fe8f:DDDD'))
act_setfield = ofp.action.set_field()
- act_setfield.field = field_2b_set
+ act_setfield.field = field_2b_set.pack() # HACK
# TODO: insert action set field properly
act_out = ofp.action.output()
act_out.port = of_ports[3]
- inst = ofp.instruction.instruction_apply_actions()
- inst.actions.add(act_setfield)
- inst.actions.add(act_out)
- request.instructions.add(inst)
+ inst = ofp.instruction.apply_actions()
+ inst.actions.append(act_setfield)
+ inst.actions.append(act_out)
+ request.instructions.append(inst)
request.buffer_id = 0xffffffff
request.priority = 1000
@@ -224,26 +222,26 @@
# Add entry match
- request = ofp.message.flow_mod()
+ request = ofp.message.flow_add()
request.match.type = ofp.OFPMT_OXM
- port = ofp.match.in_port(of_ports[0])
- eth_type = ofp.match.eth_type(IPV6_ETHERTYPE)
- ipv6_src = ofp.match.ipv6_src(ipaddr.IPv6Address('fe80::2420:52ff:fe8f:5189'))
- ip_proto = ofp.match.ip_proto(TCP_PROTOCOL)
- tcp_port = ofp.match.tcp_src(80)
+ port = ofp.oxm.in_port(of_ports[0])
+ eth_type = ofp.oxm.eth_type(IPV6_ETHERTYPE)
+ ipv6_src = ofp.oxm.ipv6_src(oftest.parse.parse_ipv6('fe80::2420:52ff:fe8f:5189'))
+ ip_proto = ofp.oxm.ip_proto(TCP_PROTOCOL)
+ tcp_port = ofp.oxm.tcp_src(80)
- request.match_fields.tlvs.append(port)
- request.match_fields.tlvs.append(eth_type)
- request.match_fields.tlvs.append(ipv6_src)
- request.match_fields.tlvs.append(ip_proto)
- request.match_fields.tlvs.append(tcp_port)
+ request.match.oxm_list.append(port)
+ request.match.oxm_list.append(eth_type)
+ request.match.oxm_list.append(ipv6_src)
+ request.match.oxm_list.append(ip_proto)
+ request.match.oxm_list.append(tcp_port)
act = ofp.action.output()
act.port = of_ports[3]
- inst = ofp.instruction.instruction_apply_actions()
- inst.actions.add(act)
- request.instructions.add(inst)
+ inst = ofp.instruction.apply_actions()
+ inst.actions.append(act)
+ request.instructions.append(inst)
request.buffer_id = 0xffffffff
request.priority = 1000