Initial set of Fabric switch test cases
Change-Id: I86fd2b67d3b773aa496f5ef61f1e1fdf51fd9925
diff --git a/Fabric/Utilities/src/python/oftest/ofdpa_utils.py b/Fabric/Utilities/src/python/oftest/ofdpa_utils.py
new file mode 100755
index 0000000..8c97b1f
--- /dev/null
+++ b/Fabric/Utilities/src/python/oftest/ofdpa_utils.py
@@ -0,0 +1,184 @@
+
+# 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.
+
+
+"""
+
+A set of inter-test utility functions for dealing with OF-DPA
+
+
+"""
+
+import logging, subprocess, time
+import ofp
+
+from oftest import config
+from oftest.testutils import *
+
+def forceOfdpaRestart( user ):
+ output = 1;
+ credential = user;
+ test = subprocess.Popen(["ssh", credential, "service ofdpa restart &> /dev/null"]);
+ time.sleep(1);
+ while output < 10:
+ output = int(subprocess.check_output(["ssh", credential, "client_cfg_purge | wc -l"]));
+ time.sleep(1);
+ subprocess.Popen(["ssh", credential, "brcm-indigo-ofdpa-ofagent -t 10.128.0.220 &> /dev/null"], stdout=subprocess.PIPE);
+
+def forceOfdpaStop( user ):
+ subprocess.Popen(["ssh", user, "ps ax | grep 'brcm-indigo-ofdpa-ofagent' | awk '{print $1}' | xargs sudo kill"], stdout=subprocess.PIPE);
+
+
+class table(object):
+ """ Metadata on each OFDPA table """
+ def __init__(self, table_id, table_name):
+ self.table_id = table_id
+ self.table_name = table_name
+ # TODO consider adding type checking verification here
+
+INGRESS_TABLE = table(0, "Ingress")
+VLAN_TABLE = table(10, "VLAN")
+MACTERM_TABLE = table(20, "MacTerm")
+UNICAST_ROUTING_TABLE = table(30, "Unicast Routing")
+MULTICAST_ROUTING_TABLE = table(40, "Multicast Routing")
+BRIDGING_TABLE = table(50, "Bridging Table")
+ACL_TABLE = table(60, "ACL Policy Table")
+#.... FIXME add all tables
+
+DEFAULT_VLAN = 1
+
+def enableVlanOnPort(controller, vlan, port=ofp.OFPP_ALL, priority=0):
+ if port == ofp.OFPP_ALL:
+ ports = sorted(config["port_map"].keys())
+ else:
+ ports = [port]
+ for port in ports:
+ tagged_match = ofp.match([
+ ofp.oxm.in_port(port),
+ ofp.oxm.vlan_vid(vlan | ofp.OFPVID_PRESENT)
+ ])
+
+ request = ofp.message.flow_add(
+ table_id = VLAN_TABLE.table_id,
+ cookie = 0xdead,
+ match = tagged_match,
+ instructions = [
+ ofp.instruction.goto_table(MACTERM_TABLE.table_id),
+# ofp.instruction.apply_actions(
+# actions=[
+# ofp.action.push_vlan(ethertype=0x8100), # DO NOT PUT THIS FOR OF-DPA 2.0 EA1 - seems to not matter for EA2
+# ofp.action.set_field(ofp.oxm.vlan_vid( ofp.OFPVID_PRESENT | vlan))
+# ]),
+ ],
+ buffer_id = ofp.OFP_NO_BUFFER,
+ priority = priority)
+
+ logging.info("Inserting vlan rule allowing tagged vlan %d on port %d" % (vlan, port))
+ controller.message_send(request)
+ do_barrier(controller)
+ verify_no_errors(controller)
+
+
+def installDefaultVlan(controller, vlan=DEFAULT_VLAN, port=ofp.OFPP_ALL, priority=0):
+ """ Insert a rule that maps all untagged traffic to vlan $vlan
+
+ In OFDPA, table 10 (the vlan table) requires that all traffic be
+ mapped to an internal vlan else the packets be dropped. This function
+ sets up a default vlan mapping all untagged traffic to an internal VLAN.
+
+ With OF-DPA, before you can insert a 'untagged to X' rule on a
+ port, you must first insert a 'X --> X' rule for the same port.
+
+ Further, the 'X --> X' rule must set ofp.OFPVID_PRESENT even
+ though 'X' is non-zero.
+
+ The 'controller' variable is self.controller from a test
+ """
+ # OFDPA seems to be dumb and wants each port set individually
+ # Can't set all ports by using OFPP_ALL
+ if port == ofp.OFPP_ALL:
+ ports = sorted(config["port_map"].keys())
+ else:
+ ports = [port]
+
+ for port in ports:
+ # enable this vlan on this port before we can map untagged packets to the vlan
+ enableVlanOnPort(controller, vlan, port)
+
+ untagged_match = ofp.match([
+ ofp.oxm.in_port(port),
+ # OFDPA 2.0 says untagged is vlan_id=0, mask=ofp.OFPVID_PRESENT
+ ofp.oxm.vlan_vid_masked(0,ofp.OFPVID_PRESENT) # WTF OFDPA 2.0EA2 -- really!?
+ ])
+
+ request = ofp.message.flow_add(
+ table_id = VLAN_TABLE.table_id,
+ cookie = 0xbeef,
+ match = untagged_match,
+ instructions = [
+ ofp.instruction.apply_actions(
+ actions=[
+ #ofp.action.push_vlan(ethertype=0x8100),
+ ofp.action.set_field(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | vlan))
+ ]),
+ ofp.instruction.goto_table(MACTERM_TABLE.table_id)
+ ],
+ buffer_id = ofp.OFP_NO_BUFFER,
+ priority = priority)
+
+ logging.info("Inserting default vlan sending all untagged traffic to vlan %d on port %d" % (vlan, port))
+ controller.message_send(request)
+ do_barrier(controller)
+ verify_no_errors(controller)
+
+
+_group_types = {
+ "L2 Interface": 0,
+ "L2 Rewrite" : 1,
+ "L3 Unicast" : 2,
+ "L2 Multicast" : 3,
+ "L2 Flood" : 4,
+ "L3 Interface" : 5,
+ "L3 Multicast": 6,
+ "L3 ECMP": 7,
+ "L2 Data Center Overlay": 8,
+ "MPLS Label" : 9,
+ "MPLS Forwarding" :10,
+ "L2 Unfiltered Interface": 11,
+ "L2 Loopback": 12,
+}
+
+
+def makeGroupID(groupType, local_id):
+ """ Group IDs in OF-DPA have rich meaning
+
+ @param groupType is a key in _group_types
+ @param local_id is an integer 0<= local_id < 2**27,
+ but it may have more semantic meaning depending on the
+ groupType
+
+
+ Read Section 4.3 of the OF-DPA manual on groups for
+ details
+ """
+ if groupType not in _group_types:
+ raise KeyError("%s not a valid OF-DPA group type" % groupType)
+ if local_id < 0 or local_id >=134217728:
+ raise ValueError("local_id %d must be 0<= local_id < 2**27" % local_id)
+ return (_group_types[groupType] << 28) + local_id
+
+
+def delete_all_recursive_groups(controller):
+ pass