blob: f3b2d1d555889898bb202bd5d3d857b8bd8cb82b [file] [log] [blame]
macauley97557232015-07-16 17:28:07 +08001import logging
2
3from oftest import config
4import oftest.base_tests as base_tests
5import ofp
6import time
7from oftest.testutils import *
8
macauleyfddc4662015-07-27 17:40:30 +08009from ncclient import manager
10import ncclient
11
macauley97557232015-07-16 17:28:07 +080012OFDPA_GROUP_TYPE_SHIFT=28
13OFDPA_VLAN_ID_SHIFT =16
macauleyfddc4662015-07-27 17:40:30 +080014OFDPA_TUNNEL_ID_SHIFT =12
15OFDPA_TUNNEL_SUBTYPE_SHIFT=10
macauley97557232015-07-16 17:28:07 +080016
17#VLAN_TABLE_FLAGS
18VLAN_TABLE_FLAG_ONLY_UNTAG=1
19VLAN_TABLE_FLAG_ONLY_TAG =2
20VLAN_TABLE_FLAG_ONLY_BOTH =3
21
macauleye8b140e2015-08-03 13:35:45 +080022PORT_FLOW_TABLE=0
23VLAN_FLOW_TABLE=10
24TERMINATION_FLOW_TABLE=20
25UCAST_ROUTING_FLOW_TABLE=30
26MCAST_ROUTING_FLOW_TABLE=40
27BRIDGE_FLOW_TABLE=50
28ACL_FLOW_TABLE=60
29
30def convertIP4toStr(ip_addr):
31 a=(ip_addr&0xff000000)>>24
32 b=(ip_addr&0x00ff0000)>>16
33 c=(ip_addr&0x0000ff00)>>8
34 d=(ip_addr&0x000000ff)
35 return str(a)+"."+str(b)+"."+str(c)+"."+str(d)
36
37def convertMACtoStr(mac):
38 if not isinstance(mac, list):
39 assert(0)
40
41 return ':'.join(['%02X' % x for x in mac])
42
macauley7f89d962015-08-06 18:13:48 +080043def getSwitchCpuMACFromDPID(dpid):
44 str_datapath_id_f= "{:016x}".format(dpid)
45 str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
46 switch_cpu_mac_str=str_datapath_id[6:]
47 switch_cpu_mac = switch_cpu_mac_str.split(":")
48 switch_cpu_mac=[int(switch_cpu_mac[i],16) for i in range(0, len(switch_cpu_mac))]
49
50 return switch_cpu_mac_str, switch_cpu_mac
macauleye8b140e2015-08-03 13:35:45 +080051
macauley97557232015-07-16 17:28:07 +080052def encode_l2_interface_group_id(vlan, id):
53 return id + (vlan << OFDPA_VLAN_ID_SHIFT)
54
55def encode_l2_rewrite_group_id(id):
56 return id + (1 << OFDPA_GROUP_TYPE_SHIFT)
57
58def encode_l3_unicast_group_id(id):
59 return id + (2 << OFDPA_GROUP_TYPE_SHIFT)
60
61def encode_l2_mcast_group_id(vlan, id):
62 return id + (vlan << OFDPA_VLAN_ID_SHIFT) + (3 << OFDPA_GROUP_TYPE_SHIFT)
63
64def encode_l2_flood_group_id(vlan, id):
65 return id + (vlan << OFDPA_VLAN_ID_SHIFT) + (4 << OFDPA_GROUP_TYPE_SHIFT)
66
67def encode_l3_interface_group_id(id):
68 return id + (5 << OFDPA_GROUP_TYPE_SHIFT)
69
70def encode_l3_mcast_group_id(vlan, id):
71 return id + (vlan << OFDPA_VLAN_ID_SHIFT)+(6 << OFDPA_GROUP_TYPE_SHIFT)
72
73def encode_l3_ecmp_group_id(id):
74 return id + (7 << OFDPA_GROUP_TYPE_SHIFT)
75
macauleyfddc4662015-07-27 17:40:30 +080076def encode_l2_overlay_group_id(tunnel_id, subtype, index):
77 tunnel_id=tunnel_id&0xffff #16 bits
78 subtype = subtype&3 #2 bits
79 index = index & 0x3f #10 bits
80 return index + (tunnel_id << OFDPA_TUNNEL_ID_SHIFT)+ (subtype<<OFDPA_TUNNEL_SUBTYPE_SHIFT)+(8 << OFDPA_GROUP_TYPE_SHIFT)
macauley97557232015-07-16 17:28:07 +080081
macauley97557232015-07-16 17:28:07 +080082def add_l2_interface_grouop(ctrl, ports, vlan_id=1, is_tagged=False, send_barrier=False):
83 # group table
84 # set up untag groups for each port
macauley41904ed2015-07-16 17:38:35 +080085 group_id_list=[]
macauley15909e72015-07-17 15:58:57 +080086 msgs=[]
macauley97557232015-07-16 17:28:07 +080087 for of_port in ports:
88 # do stuff
89 group_id = encode_l2_interface_group_id(vlan_id, of_port)
macauley41904ed2015-07-16 17:38:35 +080090 group_id_list.append(group_id)
macauley97557232015-07-16 17:28:07 +080091 if is_tagged:
92 actions = [
93 ofp.action.output(of_port),
94 ]
95 else:
96 actions = [
97 ofp.action.pop_vlan(),
98 ofp.action.output(of_port),
99 ]
100
101 buckets = [
102 ofp.bucket(actions=actions),
103 ]
104
105 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
106 group_id=group_id,
107 buckets=buckets
108 )
109 ctrl.message_send(request)
macauley15909e72015-07-17 15:58:57 +0800110 msgs.append(request)
macauley97557232015-07-16 17:28:07 +0800111
112 if send_barrier:
113 do_barrier(ctrl)
macauley41904ed2015-07-16 17:38:35 +0800114
macauley15909e72015-07-17 15:58:57 +0800115 return group_id_list, msgs
macauley97557232015-07-16 17:28:07 +0800116
macauley0f91a3e2015-07-17 18:09:59 +0800117def add_one_l2_interface_grouop(ctrl, port, vlan_id=1, is_tagged=False, send_barrier=False):
118 # group table
119 # set up untag groups for each port
120 group_id = encode_l2_interface_group_id(vlan_id, port)
121
122 if is_tagged:
123 actions = [
124 ofp.action.output(port),
125 ]
126 else:
127 actions = [
128 ofp.action.pop_vlan(),
129 ofp.action.output(port),
130 ]
131
132 buckets = [
133 ofp.bucket(actions=actions),
134 ]
135
136 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
137 group_id=group_id,
138 buckets=buckets
139 )
140 ctrl.message_send(request)
141
142 if send_barrier:
143 do_barrier(ctrl)
144
145 return group_id, request
146
macauley97557232015-07-16 17:28:07 +0800147def add_l2_mcast_group(ctrl, ports, vlanid, mcast_grp_index):
148 buckets=[]
149 for of_port in ports:
150 group_id = encode_l2_interface_group_id(vlanid, of_port)
151 action=[ofp.action.group(group_id)]
152 buckets.append(ofp.bucket(actions=action))
153
154 group_id =encode_l2_mcast_group_id(vlanid, mcast_grp_index)
155 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
156 group_id=group_id,
157 buckets=buckets
158 )
159 ctrl.message_send(request)
macauley15909e72015-07-17 15:58:57 +0800160 return request
macauley97557232015-07-16 17:28:07 +0800161
macauley15909e72015-07-17 15:58:57 +0800162def add_l2_flood_group(ctrl, ports, vlanid, id):
163 buckets=[]
164 for of_port in ports:
165 group_id = encode_l2_interface_group_id(vlanid, of_port)
166 action=[ofp.action.group(group_id)]
167 buckets.append(ofp.bucket(actions=action))
macauley97557232015-07-16 17:28:07 +0800168
macauley15909e72015-07-17 15:58:57 +0800169 group_id =encode_l2_flood_group_id(vlanid, id)
170 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
171 group_id=group_id,
172 buckets=buckets
173 )
174 ctrl.message_send(request)
175 return request
176
177def add_l2_rewrite_group(ctrl, port, vlanid, id, src_mac, dst_mac):
178 group_id = encode_l2_interface_group_id(vlanid, port)
179
180 action=[]
181 if src_mac is not None:
182 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
183
184 if dst_mac is not None:
185 action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
186
187 action.append(ofp.action.group(group_id))
188
189 buckets = [ofp.bucket(actions=action)]
190
191 group_id =encode_l2_rewrite_group_id(id)
192 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
193 group_id=group_id,
194 buckets=buckets
195 )
196 ctrl.message_send(request)
197 return request
198
199def add_l3_unicast_group(ctrl, port, vlanid, id, src_mac, dst_mac):
200 group_id = encode_l2_interface_group_id(vlanid, port)
201
202 action=[]
203 if src_mac is not None:
204 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
205
206 if dst_mac is not None:
207 action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
208
209 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(vlanid)))
210
211 action.append(ofp.action.group(group_id))
212
213 buckets = [ofp.bucket(actions=action)]
214
215 group_id =encode_l3_unicast_group_id(id)
216 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
217 group_id=group_id,
218 buckets=buckets
219 )
220 ctrl.message_send(request)
221 return request
222
223def add_l3_interface_group(ctrl, port, vlanid, id, src_mac):
224 group_id = encode_l2_interface_group_id(vlanid, port)
225
226 action=[]
227 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
228 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(vlanid)))
229 action.append(ofp.action.group(group_id))
230
231 buckets = [ofp.bucket(actions=action)]
232
233 group_id =encode_l3_interface_group_id(id)
234 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
235 group_id=group_id,
236 buckets=buckets
237 )
238 ctrl.message_send(request)
239 return request
240
241def add_l3_ecmp_group(ctrl, id, l3_ucast_groups):
242 buckets=[]
243 for group in l3_ucast_groups:
244 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
245
246 group_id =encode_l3_ecmp_group_id(id)
247 request = ofp.message.group_add(group_type=ofp.OFPGT_SELECT,
248 group_id=group_id,
249 buckets=buckets
250 )
251 ctrl.message_send(request)
252 return request
253
254def add_l3_mcast_group(ctrl, vid, mcast_group_id, groups_on_buckets):
255 buckets=[]
256 for group in groups_on_buckets:
257 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
258
259 group_id =encode_l3_mcast_group_id(vid, mcast_group_id)
260 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
261 group_id=group_id,
262 buckets=buckets
263 )
264 ctrl.message_send(request)
265 return request
macauleyfddc4662015-07-27 17:40:30 +0800266
267def add_l2_overlay_flood_over_unicast_tunnel_group(ctrl, tunnel_id, ports, index):
268 buckets=[]
269 for port in ports:
270 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
271
272 group_id=encode_l2_overlay_group_id(tunnel_id, 0, index)
273 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
274 group_id=group_id,
275 buckets=buckets
276 )
277 ctrl.message_send(request)
278 return request
279
280def add_l2_overlay_flood_over_mcast_tunnel_group(ctrl, tunnel_id, ports, index):
281 buckets=[]
282 for port in ports:
283 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
284
285 group_id=encode_l2_overlay_group_id(tunnel_id, 1, index)
286 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
287 group_id=group_id,
288 buckets=buckets
289 )
290 ctrl.message_send(request)
291 return request
292
293def add_l2_overlay_mcast_over_unicast_tunnel_group(ctrl, tunnel_id, ports, index):
294 buckets=[]
295 for port in ports:
296 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
297
298 group_id=encode_l2_overlay_group_id(tunnel_id, 2, index)
299 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
300 group_id=group_id,
301 buckets=buckets
302 )
303 ctrl.message_send(request)
304 return request
305
306def add_l2_overlay_mcast_over_mcast_tunnel_group(ctrl, tunnel_id, ports, index):
307 buckets=[]
308 for port in ports:
309 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
310
311 group_id=encode_l2_overlay_group_id(tunnel_id, 3, index)
312 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
313 group_id=group_id,
314 buckets=buckets
315 )
316 ctrl.message_send(request)
317 return request
318
319def add_port_table_flow(ctrl, is_overlay=True):
320 match = ofp.match()
321
322 if is_overlay == True:
323 match.oxm_list.append(ofp.oxm.in_port(0x10000))
macauleydbff3272015-07-30 14:07:16 +0800324 NEXT_TABLE=50
macauleyfddc4662015-07-27 17:40:30 +0800325 else:
326 match.oxm_list.append(ofp.oxm.in_port(0))
macauleydbff3272015-07-30 14:07:16 +0800327 NEXT_TABLE=10
macauleyfddc4662015-07-27 17:40:30 +0800328
329 request = ofp.message.flow_add(
330 table_id=0,
331 cookie=42,
332 match=match,
333 instructions=[
macauleydbff3272015-07-30 14:07:16 +0800334 ofp.instruction.goto_table(NEXT_TABLE)
macauleyfddc4662015-07-27 17:40:30 +0800335 ],
336 priority=0)
337 logging.info("Add port table, match port %lx" % 0x10000)
338 ctrl.message_send(request)
macauleydbff3272015-07-30 14:07:16 +0800339
340
macauleyfddc4662015-07-27 17:40:30 +0800341
macauley97557232015-07-16 17:28:07 +0800342def add_vlan_table_flow(ctrl, ports, vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
343 # table 10: vlan
344 # goto to table 20
macauley15909e72015-07-17 15:58:57 +0800345 msgs=[]
macauley97557232015-07-16 17:28:07 +0800346 for of_port in ports:
347 if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
348 match = ofp.match()
349 match.oxm_list.append(ofp.oxm.in_port(of_port))
350 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
351 request = ofp.message.flow_add(
352 table_id=10,
353 cookie=42,
354 match=match,
355 instructions=[
356 ofp.instruction.goto_table(20)
357 ],
358 priority=0)
359 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
360 ctrl.message_send(request)
361
362 if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
363 match = ofp.match()
364 match.oxm_list.append(ofp.oxm.in_port(of_port))
365 match.oxm_list.append(ofp.oxm.vlan_vid(0))
366 request = ofp.message.flow_add(
367 table_id=10,
368 cookie=42,
369 match=match,
370 instructions=[
371 ofp.instruction.apply_actions(
372 actions=[
373 ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id))
374 ]
375 ),
376 ofp.instruction.goto_table(20)
377 ],
378 priority=0)
379 logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
380 ctrl.message_send(request)
macauley15909e72015-07-17 15:58:57 +0800381 msgs.append(request)
macauley97557232015-07-16 17:28:07 +0800382
383 if send_barrier:
384 do_barrier(ctrl)
385
macauley15909e72015-07-17 15:58:57 +0800386 return msgs
macauley0f91a3e2015-07-17 18:09:59 +0800387
macauley53d90fe2015-08-04 17:34:22 +0800388def add_one_vlan_table_flow(ctrl, of_port, vlan_id=1, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
macauley0f91a3e2015-07-17 18:09:59 +0800389 # table 10: vlan
390 # goto to table 20
391 if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
392 match = ofp.match()
393 match.oxm_list.append(ofp.oxm.in_port(of_port))
394 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
macauley7f89d962015-08-06 18:13:48 +0800395
396 actions=[]
397 if vrf!=0:
398 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
399
400 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(value=vlan_id)))
401
macauley0f91a3e2015-07-17 18:09:59 +0800402 request = ofp.message.flow_add(
403 table_id=10,
404 cookie=42,
405 match=match,
406 instructions=[
macauley53d90fe2015-08-04 17:34:22 +0800407 ofp.instruction.apply_actions(
macauley7f89d962015-08-06 18:13:48 +0800408 actions=actions
macauley53d90fe2015-08-04 17:34:22 +0800409 ),
410 ofp.instruction.goto_table(20)
macauley0f91a3e2015-07-17 18:09:59 +0800411 ],
412 priority=0)
413 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
414 ctrl.message_send(request)
415
416 if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
417 match = ofp.match()
418 match.oxm_list.append(ofp.oxm.in_port(of_port))
419 match.oxm_list.append(ofp.oxm.vlan_vid(0))
macauley53d90fe2015-08-04 17:34:22 +0800420
macauley7f89d962015-08-06 18:13:48 +0800421 actions=[]
422 if vrf!=0:
423 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
424
425 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
426
macauley0f91a3e2015-07-17 18:09:59 +0800427 request = ofp.message.flow_add(
428 table_id=10,
429 cookie=42,
430 match=match,
431 instructions=[
432 ofp.instruction.apply_actions(
macauley7f89d962015-08-06 18:13:48 +0800433 actions=actions
macauley0f91a3e2015-07-17 18:09:59 +0800434 ),
435 ofp.instruction.goto_table(20)
436 ],
437 priority=0)
438 logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
439 ctrl.message_send(request)
440
441 if send_barrier:
442 do_barrier(ctrl)
443
444 return request
macauley15909e72015-07-17 15:58:57 +0800445
macauley97557232015-07-16 17:28:07 +0800446def add_bridge_flow(ctrl, dst_mac, vlanid, group_id, send_barrier=False):
447 match = ofp.match()
macauleyfddc4662015-07-27 17:40:30 +0800448 if dst_mac!=None:
449 match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
450
macauley97557232015-07-16 17:28:07 +0800451 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
macauleyfddc4662015-07-27 17:40:30 +0800452
macauley97557232015-07-16 17:28:07 +0800453 request = ofp.message.flow_add(
454 table_id=50,
455 cookie=42,
456 match=match,
457 instructions=[
458 ofp.instruction.write_actions(
459 actions=[
460 ofp.action.group(group_id)]),
461 ofp.instruction.goto_table(60)
462 ],
463 buffer_id=ofp.OFP_NO_BUFFER,
464 priority=1000)
465
466 logging.info("Inserting Brdige flow vlan %d, mac %s", vlanid, dst_mac)
467 ctrl.message_send(request)
468
469 if send_barrier:
macauley15909e72015-07-17 15:58:57 +0800470 do_barrier(ctrl)
471
macauley0f91a3e2015-07-17 18:09:59 +0800472 return request
macauleyfddc4662015-07-27 17:40:30 +0800473
474def add_overlay_bridge_flow(ctrl, dst_mac, vnid, group_id, is_group=True, send_barrier=False):
475 match = ofp.match()
476 if dst_mac!=None:
477 match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
478
479 match.oxm_list.append(ofp.oxm.tunnel_id(vnid))
480 if is_group == True:
481 actions=[ofp.action.group(group_id)]
482 else:
483 actions=[ofp.action.output(group_id)]
484
485 request = ofp.message.flow_add(
486 table_id=50,
487 cookie=42,
488 match=match,
489 instructions=[
490 ofp.instruction.write_actions(
491 actions=actions),
492 ofp.instruction.goto_table(60)
493 ],
494 buffer_id=ofp.OFP_NO_BUFFER,
495 priority=1000)
496
497 logging.info("Inserting Brdige flow vnid %d, mac %s", vnid, dst_mac)
498 ctrl.message_send(request)
499
500 if send_barrier:
501 do_barrier(ctrl)
502
503 return request
macauley0f91a3e2015-07-17 18:09:59 +0800504
505def add_termination_flow(ctrl, in_port, eth_type, dst_mac, vlanid, send_barrier=False):
506 match = ofp.match()
macauley0f91a3e2015-07-17 18:09:59 +0800507 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
macauleyfddc4662015-07-27 17:40:30 +0800508 if dst_mac[0]&0x01 == 0x01:
509 match.oxm_list.append(ofp.oxm.eth_dst_masked(dst_mac, [0xff, 0xff, 0xff, 0x80, 0x00, 0x00]))
510 goto_table=40
511 else:
macauley53d90fe2015-08-04 17:34:22 +0800512 if in_port!=0:
513 match.oxm_list.append(ofp.oxm.in_port(in_port))
macauleyfddc4662015-07-27 17:40:30 +0800514 match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
515 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
516 goto_table=30
macauley0f91a3e2015-07-17 18:09:59 +0800517
518 request = ofp.message.flow_add(
519 table_id=20,
520 cookie=42,
521 match=match,
522 instructions=[
523 ofp.instruction.goto_table(goto_table)
524 ],
525 buffer_id=ofp.OFP_NO_BUFFER,
526 priority=1)
527
528 logging.info("Inserting termination flow inport %d, eth_type %lx, vlan %d, mac %s", in_port, eth_type, vlanid, dst_mac)
529 ctrl.message_send(request)
530
531 if send_barrier:
532 do_barrier(ctrl)
533
534 return request
535
macauley53d90fe2015-08-04 17:34:22 +0800536def add_unicast_routing_flow(ctrl, eth_type, dst_ip, mask, action_group_id, vrf=0, send_barrier=False):
macauley0f91a3e2015-07-17 18:09:59 +0800537 match = ofp.match()
538 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
macauley53d90fe2015-08-04 17:34:22 +0800539 if vrf != 0:
540 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
541
macauleyf8b1acd2015-07-23 15:13:13 +0800542 if mask!=0:
543 match.oxm_list.append(ofp.oxm.ipv4_dst_masked(dst_ip, mask))
544 else:
545 match.oxm_list.append(ofp.oxm.ipv4_dst(dst_ip))
macauley0f91a3e2015-07-17 18:09:59 +0800546
macauley53d90fe2015-08-04 17:34:22 +0800547
macauley0f91a3e2015-07-17 18:09:59 +0800548 request = ofp.message.flow_add(
549 table_id=30,
550 cookie=42,
551 match=match,
552 instructions=[
553 ofp.instruction.write_actions(
554 actions=[ofp.action.group(action_group_id)]),
555 ofp.instruction.goto_table(60)
556 ],
557 buffer_id=ofp.OFP_NO_BUFFER,
558 priority=1)
559
560 logging.info("Inserting unicast routing flow eth_type %lx, dip %ld",eth_type, dst_ip)
561 ctrl.message_send(request)
562
563 if send_barrier:
564 do_barrier(ctrl)
565
macauleyfddc4662015-07-27 17:40:30 +0800566 return request
567
568def add_mcast4_routing_flow(ctrl, vlan_id, src_ip, src_ip_mask, dst_ip, action_group_id, send_barrier=False):
569 match = ofp.match()
570 match.oxm_list.append(ofp.oxm.eth_type(0x0800))
571 match.oxm_list.append(ofp.oxm.vlan_vid(vlan_id))
572 if src_ip_mask!=0:
573 match.oxm_list.append(ofp.oxm.ipv4_src_masked(src_ip, src_ip_mask))
574 else:
575 match.oxm_list.append(ofp.oxm.ipv4_src(src_ip))
576
577 match.oxm_list.append(ofp.oxm.ipv4_dst(dst_ip))
578
579 request = ofp.message.flow_add(
580 table_id=40,
581 cookie=42,
582 match=match,
583 instructions=[
584 ofp.instruction.write_actions(
585 actions=[ofp.action.group(action_group_id)]),
586 ofp.instruction.goto_table(60)
587 ],
588 buffer_id=ofp.OFP_NO_BUFFER,
589 priority=1)
590
591 logging.info("Inserting mcast routing flow eth_type %lx, dip %lx, sip %lx, sip_mask %lx",0x0800, dst_ip, src_ip, src_ip_mask)
592 ctrl.message_send(request)
593
594 if send_barrier:
595 do_barrier(ctrl)
596
597 return request
598
599def get_vtap_lport_config_xml(dp_id, lport, phy_port, vlan, vnid, operation='merge'):
600 """
601 Command Example:
602 of-agent vtap 10001 ethernet 1/1 vid 1
603 of-agent vtp 10001 vni 10
604 """
605 if vlan != 0:
606 config_vtap_xml="""
607 <config>
608 <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
609 <id>capable-switch-1</id>
610 <resources>
611 <port xc:operation="OPERATION">
612 <resource-id >LPORT</resource-id>
613 <features>
614 <current>
615 <rate>10Gb</rate>
616 <medium>fiber</medium>
617 <pause>symmetric</pause>
618 </current>
619 <advertised>
620 <rate>10Gb</rate>
621 <rate>100Gb</rate>
622 <medium>fiber</medium>
623 <pause>symmetric</pause>
624 </advertised>
625 <supported>
626 <rate>10Gb</rate>
627 <rate>100Gb</rate>
628 <medium>fiber</medium>
629 <pause>symmetric</pause>
630 </supported>
631 <advertised-peer>
632 <rate>10Gb</rate>
633 <rate>100Gb</rate>
634 <medium>fiber</medium>
635 <pause>symmetric</pause>
636 </advertised-peer>
637 </features>
638 <ofdpa10:vtap xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
639 <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
640 <ofdpa10:vid>VLAN_ID</ofdpa10:vid>
641 <ofdpa10:vni>VNID</ofdpa10:vni>
642 </ofdpa10:vtap>
643 </port>
644 </resources>
645 <logical-switches>
646 <switch>
647 <id>DATAPATH_ID</id>
648 <datapath-id>DATAPATH_ID</datapath-id>
649 <resources>
650 <port xc:operation="OPERATION">LPORT</port>
651 </resources>
652 </switch>
653 </logical-switches>
654 </capable-switch>
655 </config>
656 """
657 else:
658 config_vtap_xml="""
659 <config>
660 <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
661 <id>capable-switch-1</id>
662 <resources>
663 <port xc:operation="OPERATION">
664 <resource-id >LPORT</resource-id>
665 <features>
666 <current>
667 <rate>10Gb</rate>
668 <medium>fiber</medium>
669 <pause>symmetric</pause>
670 </current>
671 <advertised>
672 <rate>10Gb</rate>
673 <rate>100Gb</rate>
674 <medium>fiber</medium>
675 <pause>symmetric</pause>
676 </advertised>
677 <supported>
678 <rate>10Gb</rate>
679 <rate>100Gb</rate>
680 <medium>fiber</medium>
681 <pause>symmetric</pause>
682 </supported>
683 <advertised-peer>
684 <rate>10Gb</rate>
685 <rate>100Gb</rate>
686 <medium>fiber</medium>
687 <pause>symmetric</pause>
688 </advertised-peer>
689 </features>
690 <ofdpa10:vtap xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
691 <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
692 <ofdpa10:vni>VNID</ofdpa10:vni>
693 </ofdpa10:vtap>
694 </port>
695 </resources>
696 <logical-switches>
697 <switch>
698 <id>DATAPATH_ID</id>
699 <datapath-id>DATAPATH_ID</datapath-id>
700 <resources>
701 <port xc:operation="OPERATION">LPORT</port>
702 </resources>
703 </switch>
704 </logical-switches>
705 </capable-switch>
706 </config>
707 """
708 str_datapath_id_f= "{:016x}".format(dp_id)
709 str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
710 config_vtap_xml=config_vtap_xml.replace("DATAPATH_ID", str_datapath_id)
711 config_vtap_xml=config_vtap_xml.replace("LPORT", str(hex(lport)))
712 config_vtap_xml=config_vtap_xml.replace("PHY_PORT", str(phy_port))
713 config_vtap_xml=config_vtap_xml.replace("VLAN_ID", str(vlan))
714 config_vtap_xml=config_vtap_xml.replace("VNID", str(vnid))
715 config_vtap_xml=config_vtap_xml.replace("OPERATION", str(operation))
716 return config_vtap_xml
717
718def get_vtep_lport_config_xml(dp_id, lport, src_ip, dst_ip, next_hop_id, vnid, udp_src_port=6633, ttl=25, operation='merge'):
719 """
720 Command Example:
721 of-agent vtep 10002 source user-input-src-ip destination user-input-dst-ip udp-source-port 6633 nexthop 2 ttl 25
722 of-agent vtp 10001 vni 10
723 """
724
725 config_vtep_xml="""
726 <config>
727 <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
728 <id>capable-switch-1</id>
729 <resources>
730 <port xc:operation="OPERATION">
731 <resource-id>LPORT</resource-id>
732 <features>
733 <current>
734 <rate>10Gb</rate>
735 <medium>fiber</medium>
736 <pause>symmetric</pause>
737 </current>
738 <advertised>
739 <rate>10Gb</rate>
740 <rate>100Gb</rate>
741 <medium>fiber</medium>
742 <pause>symmetric</pause>
743 </advertised>
744 <supported>
745 <rate>10Gb</rate>
746 <rate>100Gb</rate>
747 <medium>fiber</medium>
748 <pause>symmetric</pause>
749 </supported>
750 <advertised-peer>
751 <rate>10Gb</rate>
752 <rate>100Gb</rate>
753 <medium>fiber</medium>
754 <pause>symmetric</pause>
755 </advertised-peer>
756 </features>
757 <ofdpa10:vtep xmlns:ofdpa10="urn:bcm:ofdpa10:accton01">
758 <ofdpa10:src-ip>SRC_IP</ofdpa10:src-ip>
759 <ofdpa10:dest-ip>DST_IP</ofdpa10:dest-ip>
760 <ofdpa10:udp-src-port>UDP_SRC_PORT</ofdpa10:udp-src-port>
761 <ofdpa10:vni>VNID</ofdpa10:vni>
762 <ofdpa10:nexthop-id>NEXT_HOP_ID</ofdpa10:nexthop-id>
763 <ofdpa10:ttl>TTL</ofdpa10:ttl>
764 </ofdpa10:vtep>
765 </port>
766 </resources>
767 <logical-switches>
768 <switch>
769 <id>DATAPATH_ID</id>
770 <datapath-id>DATAPATH_ID</datapath-id>
771 <resources>
772 <port xc:operation="OPERATION">LPORT</port>
773 </resources>
774 </switch>
775 </logical-switches>
776 </capable-switch>
777 </config>
778 """
779 str_datapath_id_f= "{:016x}".format(dp_id)
780 str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
781 config_vtep_xml=config_vtep_xml.replace("DATAPATH_ID", str_datapath_id)
782 config_vtep_xml=config_vtep_xml.replace("LPORT", str(hex(lport)))
783 config_vtep_xml=config_vtep_xml.replace("SRC_IP", str(src_ip))
784 config_vtep_xml=config_vtep_xml.replace("DST_IP", str(dst_ip))
785 config_vtep_xml=config_vtep_xml.replace("UDP_SRC_PORT", str(udp_src_port))
786 config_vtep_xml=config_vtep_xml.replace("NEXT_HOP_ID", str(next_hop_id))
787 config_vtep_xml=config_vtep_xml.replace("TTL", str(ttl))
788 config_vtep_xml=config_vtep_xml.replace("VNID", str(vnid))
789 config_vtep_xml=config_vtep_xml.replace("OPERATION", str(operation))
790
791 return config_vtep_xml
792
793def get_next_hop_config_xml(next_hop_id, dst_mac, phy_port, vlan, operation='merge'):
794 #of-agent nexthop 2 destination user-input-dst-mac ethernet 1/2 vid 2
795 config_nexthop_xml="""
796 <config>
797 <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
798 <ofdpa10:next-hop xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
799 <ofdpa10:id>NEXT_HOP_ID</ofdpa10:id>
800 <ofdpa10:dest-mac>DST_MAC</ofdpa10:dest-mac>
801 <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
802 <ofdpa10:vid>VLAN_ID</ofdpa10:vid>
803 </ofdpa10:next-hop>
804 </of11-config:capable-switch>
805 </config>
806 """
807 config_nexthop_xml=config_nexthop_xml.replace("VLAN_ID", str(vlan))
808 config_nexthop_xml=config_nexthop_xml.replace("PHY_PORT", str(phy_port))
809 config_nexthop_xml=config_nexthop_xml.replace("NEXT_HOP_ID", str(next_hop_id))
810 config_nexthop_xml=config_nexthop_xml.replace("DST_MAC", str(dst_mac))
811 config_nexthop_xml=config_nexthop_xml.replace("OPERATION", str(operation))
812 return config_nexthop_xml
813
814def get_vni_config_xml(vni_id, mcast_ipv4, next_hop_id, operation='merge'):
815 #of-agent vni 10 multicast 224.1.1.1 nexthop 20
816 if mcast_ipv4!=None:
817 config_vni_xml="""
818 <config>
819 <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
820 <ofdpa10:vni xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
821 <ofdpa10:id>VNID</ofdpa10:id>
822 <ofdpa10:vni-multicast-group>MCAST_IP</ofdpa10:vni-multicast-group>
823 <ofdpa10:multicast-group-nexthop-id>NEXT_HOP_ID</ofdpa10:multicast-group-nexthop-id>
824 </ofdpa10:vni>
825 </of11-config:capable-switch>
826 </config>
827 """
828 config_vni_xml=config_vni_xml.replace("NEXT_HOP_ID", str(next_hop_id))
829 config_vni_xml=config_vni_xml.replace("MCAST_IP", str(mcast_ipv4))
830 else:
831 config_vni_xml="""
832 <config>
833 <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
834 <ofdpa10:vni xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
835 <ofdpa10:id>VNID</ofdpa10:id>
836 </ofdpa10:vni>
837 </of11-config:capable-switch>
838 </config>
839 """
840
841 config_vni_xml=config_vni_xml.replace("VNID", str(vni_id))
842 config_vni_xml=config_vni_xml.replace("OPERATION", str(operation))
843 return config_vni_xml
844
845def get_featureReplay(self):
846 req = ofp.message.features_request()
847 res, raw = self.controller.transact(req)
848 self.assertIsNotNone(res, "Did not receive a response from the DUT.")
849 self.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
850 ("Unexpected packet type %d received in response to "
851 "OFPT_FEATURES_REQUEST") % res.type)
852 return res
853
854def send_edit_config(switch_ip, xml, target='runing'):
855 NETCONF_ACCOUNT="netconfuser"
856 NETCONF_PASSWD="netconfuser"
857 with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
858 try:
859 m.edit_config(target='running',
860 config=xml,
861 default_operation='merge',
862 error_option='stop-on-error')
863
864 except Exception as e:
865 logging.info("Fail to set xml %s", xml)
866 return False
867
868 #return m.get_config(source='running').data_xml
869 return True
870
871def send_delete_config(switch_ip, xml, target='runing'):
872 NETCONF_ACCOUNT="netconfuser"
873 NETCONF_PASSWD="netconfuser"
874 with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
875 try:
876 m.edit_config(target='running',
877 config=xml,
878 default_operation='delete',
879 error_option='stop-on-error')
880
881 except Exception as e:
882 logging.info("Fail to set xml %s", xml)
883 return False
884
885 #return m.get_config(source='running').data_xml
886 return True
887
888def get_edit_config(switch_ip, target='runing'):
889 NETCONF_ACCOUNT="netconfuser"
890 NETCONF_PASSWD="netconfuser"
891 with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
892 print m.get_config(source='running').data_xml
macauleydbff3272015-07-30 14:07:16 +0800893
894
895def print_current_table_flow_stat(ctrl, table_id=0xff):
896 stat_req=ofp.message.flow_stats_request()
897 response, pkt = ctrl.transact(stat_req)
898 if response == None:
899 print "no response"
900 return None
901 print len(response.entries)
902 for obj in response.entries:
903 print "match ", obj.match
904 print "cookie", obj.cookie
905 print "priority", obj.priority
906 print "idle_timeout", obj.idle_timeout
907 print "hard_timeout", obj.hard_timeout
908 #obj.actions
909 print "packet count: %lx"%obj.packet_count