blob: ebbc834a9e04c8aa8cd88b70c0be8bd6de9e0936 [file] [log] [blame]
Flavio Castro96646c62015-11-16 15:05:43 -05001"""
2
3A set of inter-test utility functions for dealing with OF-DPA
4
5
6"""
7
Flavio Castrob01d0aa2016-07-20 16:14:48 -07008import logging, subprocess, time
Flavio Castro96646c62015-11-16 15:05:43 -05009import ofp
10
11from oftest import config
12from oftest.testutils import *
13
Flavio Castrob01d0aa2016-07-20 16:14:48 -070014def forceOfdpaRestart( user ):
15 output = 1;
16 credential = user;
17 test = subprocess.Popen(["ssh", credential, "service ofdpa restart &> /dev/null"]);
18 time.sleep(1);
19 while output < 10:
20 output = int(subprocess.check_output(["ssh", credential, "client_cfg_purge | wc -l"]));
21 time.sleep(1);
22 subprocess.Popen(["ssh", credential, "brcm-indigo-ofdpa-ofagent -t 10.128.0.220 &> /dev/null"], stdout=subprocess.PIPE);
23
24def forceOfdpaStop( user ):
25 subprocess.Popen(["ssh", user, "ps ax | grep 'brcm-indigo-ofdpa-ofagent' | awk '{print $1}' | xargs sudo kill"], stdout=subprocess.PIPE);
Flavio Castro96646c62015-11-16 15:05:43 -050026
27
28class table(object):
29 """ Metadata on each OFDPA table """
30 def __init__(self, table_id, table_name):
31 self.table_id = table_id
32 self.table_name = table_name
33 # TODO consider adding type checking verification here
34
35INGRESS_TABLE = table(0, "Ingress")
36VLAN_TABLE = table(10, "VLAN")
37MACTERM_TABLE = table(20, "MacTerm")
38UNICAST_ROUTING_TABLE = table(30, "Unicast Routing")
39MULTICAST_ROUTING_TABLE = table(40, "Multicast Routing")
40BRIDGING_TABLE = table(50, "Bridging Table")
41ACL_TABLE = table(60, "ACL Policy Table")
42#.... FIXME add all tables
43
44DEFAULT_VLAN = 1
45
46def enableVlanOnPort(controller, vlan, port=ofp.OFPP_ALL, priority=0):
47 if port == ofp.OFPP_ALL:
48 ports = sorted(config["port_map"].keys())
49 else:
50 ports = [port]
51 for port in ports:
52 tagged_match = ofp.match([
53 ofp.oxm.in_port(port),
54 ofp.oxm.vlan_vid(vlan | ofp.OFPVID_PRESENT)
55 ])
56
57 request = ofp.message.flow_add(
58 table_id = VLAN_TABLE.table_id,
59 cookie = 0xdead,
60 match = tagged_match,
61 instructions = [
62 ofp.instruction.goto_table(MACTERM_TABLE.table_id),
63# ofp.instruction.apply_actions(
64# actions=[
65# ofp.action.push_vlan(ethertype=0x8100), # DO NOT PUT THIS FOR OF-DPA 2.0 EA1 - seems to not matter for EA2
66# ofp.action.set_field(ofp.oxm.vlan_vid( ofp.OFPVID_PRESENT | vlan))
67# ]),
68 ],
69 buffer_id = ofp.OFP_NO_BUFFER,
70 priority = priority)
71
72 logging.info("Inserting vlan rule allowing tagged vlan %d on port %d" % (vlan, port))
73 controller.message_send(request)
74 do_barrier(controller)
75 verify_no_errors(controller)
76
77
78def installDefaultVlan(controller, vlan=DEFAULT_VLAN, port=ofp.OFPP_ALL, priority=0):
79 """ Insert a rule that maps all untagged traffic to vlan $vlan
80
81 In OFDPA, table 10 (the vlan table) requires that all traffic be
82 mapped to an internal vlan else the packets be dropped. This function
83 sets up a default vlan mapping all untagged traffic to an internal VLAN.
84
85 With OF-DPA, before you can insert a 'untagged to X' rule on a
86 port, you must first insert a 'X --> X' rule for the same port.
87
88 Further, the 'X --> X' rule must set ofp.OFPVID_PRESENT even
89 though 'X' is non-zero.
90
91 The 'controller' variable is self.controller from a test
92 """
93 # OFDPA seems to be dumb and wants each port set individually
94 # Can't set all ports by using OFPP_ALL
95 if port == ofp.OFPP_ALL:
96 ports = sorted(config["port_map"].keys())
97 else:
98 ports = [port]
99
100 for port in ports:
101 # enable this vlan on this port before we can map untagged packets to the vlan
102 enableVlanOnPort(controller, vlan, port)
103
104 untagged_match = ofp.match([
105 ofp.oxm.in_port(port),
106 # OFDPA 2.0 says untagged is vlan_id=0, mask=ofp.OFPVID_PRESENT
107 ofp.oxm.vlan_vid_masked(0,ofp.OFPVID_PRESENT) # WTF OFDPA 2.0EA2 -- really!?
108 ])
109
110 request = ofp.message.flow_add(
111 table_id = VLAN_TABLE.table_id,
112 cookie = 0xbeef,
113 match = untagged_match,
114 instructions = [
115 ofp.instruction.apply_actions(
116 actions=[
117 #ofp.action.push_vlan(ethertype=0x8100),
118 ofp.action.set_field(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | vlan))
119 ]),
120 ofp.instruction.goto_table(MACTERM_TABLE.table_id)
121 ],
122 buffer_id = ofp.OFP_NO_BUFFER,
123 priority = priority)
124
125 logging.info("Inserting default vlan sending all untagged traffic to vlan %d on port %d" % (vlan, port))
126 controller.message_send(request)
127 do_barrier(controller)
128 verify_no_errors(controller)
129
130
131_group_types = {
132 "L2 Interface": 0,
133 "L2 Rewrite" : 1,
134 "L3 Unicast" : 2,
135 "L2 Multicast" : 3,
136 "L2 Flood" : 4,
137 "L3 Interface" : 5,
138 "L3 Multicast": 6,
139 "L3 ECMP": 7,
140 "L2 Data Center Overlay": 8,
141 "MPLS Label" : 9,
142 "MPLS Forwarding" :10,
143 "L2 Unfiltered Interface": 11,
144 "L2 Loopback": 12,
145}
146
147
148def makeGroupID(groupType, local_id):
149 """ Group IDs in OF-DPA have rich meaning
150
151 @param groupType is a key in _group_types
152 @param local_id is an integer 0<= local_id < 2**27,
153 but it may have more semantic meaning depending on the
154 groupType
155
156
157 Read Section 4.3 of the OF-DPA manual on groups for
158 details
159 """
160 if groupType not in _group_types:
161 raise KeyError("%s not a valid OF-DPA group type" % groupType)
162 if local_id < 0 or local_id >=134217728:
163 raise ValueError("local_id %d must be 0<= local_id < 2**27" % local_id)
164 return (_group_types[groupType] << 28) + local_id
165
166
167def delete_all_recursive_groups(controller):
168 pass