blob: 0f32e760b2cbe112e8762202d27b9fec45c0d147 [file] [log] [blame]
Sreeju Sreedhare3fefd92019-04-02 15:57:15 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15
16import logging
17
18from oftest import config
19import oftest.base_tests as base_tests
20import ofp
21import time
22from oftest.testutils import *
23from oftest.parse import parse_ipv6
24
25from ncclient import manager
26import ncclient
27
28OFDPA_GROUP_TYPE_SHIFT=28
29OFDPA_VLAN_ID_SHIFT =16
30OFDPA_TUNNEL_ID_SHIFT =12
31OFDPA_TUNNEL_SUBTYPE_SHIFT=10
32
33#VLAN_TABLE_FLAGS
34VLAN_TABLE_FLAG_ONLY_UNTAG=1
35VLAN_TABLE_FLAG_ONLY_TAG =2
36VLAN_TABLE_FLAG_ONLY_BOTH =3
37VLAN_TABLE_FLAG_ONLY_STACKED=5
38VLAN_TABLE_FLAG_PRIORITY=6
39VLAN_TABLE_FLAG_ONLY_UNTAG_PRIORITY=7
40VLAN_TABLE_FLAG_ONLY_POP_VLAN=8
41
42PORT_FLOW_TABLE=0
43VLAN_FLOW_TABLE=10
44VLAN_1_FLOW_TABLE=11
45MPLS_L2_PORT_FLOW_TABLE=13
46MPLS_L2_PORT_DSCP_TRUST_FLOW_TABLE=15
47MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE=16
48TERMINATION_FLOW_TABLE=20
49MPLS_TYPE_FLOW_TABLE=29
50UCAST_ROUTING_FLOW_TABLE=30
51MCAST_ROUTING_FLOW_TABLE=40
52BRIDGE_FLOW_TABLE=50
53ACL_FLOW_TABLE=60
54EGRESS_TPID_FLOW_TABLE = 235
55
56ONF_EXPERIMENTER_ID = 0x4F4E4600
57
58EGRESS_VLAN_FLOW_TABLE=210
59EGRESS_VLAN_1_FLOW_TABLE=211
60EGRESS_MAINTENANCE_POINT_FLOW_TABLE=226
61EGRESS_DSCP_TABLE=230
62EGRESS_TPID_TABLE=235
63EGRESS_SOURCE_MAC_LEARNING_TABLE=254
64
65def convertIP4toStr(ip_addr):
66 a=(ip_addr&0xff000000)>>24
67 b=(ip_addr&0x00ff0000)>>16
68 c=(ip_addr&0x0000ff00)>>8
69 d=(ip_addr&0x000000ff)
70 return str(a)+"."+str(b)+"."+str(c)+"."+str(d)
71
72def convertMACtoStr(mac):
73 if not isinstance(mac, list):
74 assert(0)
75
76 return ':'.join(['%02X' % x for x in mac])
77
78def getSwitchCpuMACFromDPID(dpid):
79 str_datapath_id_f= "{:016x}".format(dpid)
80 str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
81 switch_cpu_mac_str=str_datapath_id[6:]
82 switch_cpu_mac = switch_cpu_mac_str.split(":")
83 switch_cpu_mac=[int(switch_cpu_mac[i],16) for i in range(0, len(switch_cpu_mac))]
84
85 return switch_cpu_mac_str, switch_cpu_mac
86
87def DumpGroup(stats, verify_group_stats, always_show=True):
88 if(len(stats) > len(verify_group_stats)):
89 min_len = len(verify_group_stats)
90 print "Stats Len is not the same, stats>verify_group_stats"
91 if(len(stats)< len(verify_group_stats)):
92 min_len = len(stats)
93 print "Stats Len is not the same, stats<verify_group_stats"
94 else:
95 min_len = len(stats)
96
97 print "\r\n"
98 for i in range(min_len):
99 gs = stats[i]
100 gv = verify_group_stats[i]
101 print "FromSwtich:(GID=%lx, TYPE=%lx)\r\nVerify :(GID=%lx, TYPE=%lx)"%(gs.group_id, gs.group_type, gv.group_id, gv.group_type)
102 if(len(gs.buckets) != len(gv.buckets)):
103 print "buckets len is not the same gs %lx, gv %lx",(len(gs.buckets), len(gv.buckets))
104
105 for j in range(len(gs.buckets)):
106 b1=gs.buckets[j]
107 b2=gv.buckets[j]
108 if(len(b1.actions) != len(b2.actions)):
109 print "action len is not the same"
110
111 for k in range(len(b1.actions)):
112 a1=b1.actions[k]
113 a2=b2.actions[k]
114 if(always_show == True):
115 print "a1:"+a1.show()
116 print "a2:"+a2.show()
117
118def AssertGroup(self, stats, verify_group_stats):
119 self.assertTrue(len(stats) ==len(verify_group_stats), "stats len is not the same")
120
121 for i in range(len(stats)):
122 gs = stats[i]
123 gv = verify_group_stats[i]
124 self.assertTrue(len(gs.buckets) == len(gv.buckets), "buckets len is not the same")
125
126 for j in range(len(gs.buckets)):
127 b1=gs.buckets[j]
128 b2=gv.buckets[j]
129 self.assertTrue(len(b1.actions) == len(b2.actions), "action len is not the same")
130
131 for k in range(len(b1.actions)):
132 a1=b1.actions[k]
133 a2=b2.actions[k]
134 self.assertEquals(a1, a2, "action is not the same")
135
136def encode_l2_interface_group_id(vlan, id):
137 return id + (vlan << OFDPA_VLAN_ID_SHIFT)
138
139def encode_l2_rewrite_group_id(id):
140 return id + (1 << OFDPA_GROUP_TYPE_SHIFT)
141
142def encode_l3_unicast_group_id(id):
143 return id + (2 << OFDPA_GROUP_TYPE_SHIFT)
144
145def encode_l2_mcast_group_id(vlan, id):
146 return id + (vlan << OFDPA_VLAN_ID_SHIFT) + (3 << OFDPA_GROUP_TYPE_SHIFT)
147
148def encode_l2_flood_group_id(vlan, id):
149 return id + (vlan << OFDPA_VLAN_ID_SHIFT) + (4 << OFDPA_GROUP_TYPE_SHIFT)
150
151def encode_l3_interface_group_id(id):
152 return id + (5 << OFDPA_GROUP_TYPE_SHIFT)
153
154def encode_l3_mcast_group_id(vlan, id):
155 return id + (vlan << OFDPA_VLAN_ID_SHIFT)+(6 << OFDPA_GROUP_TYPE_SHIFT)
156
157def encode_l3_ecmp_group_id(id):
158 return id + (7 << OFDPA_GROUP_TYPE_SHIFT)
159
160def encode_l2_unfiltered_group_id(id):
161 return id + (11 << OFDPA_GROUP_TYPE_SHIFT)
162
163def encode_l2_loadbal_group_id(id):
164 return id + (12 << OFDPA_GROUP_TYPE_SHIFT)
165
166def encode_l2_overlay_group_id(tunnel_id, subtype, index):
167 tunnel_id=tunnel_id&0xffff #16 bits
168 subtype = subtype&3 #2 bits
169 index = index & 0x3f #10 bits
170 return index + (tunnel_id << OFDPA_TUNNEL_ID_SHIFT)+ (subtype<<OFDPA_TUNNEL_SUBTYPE_SHIFT)+(8 << OFDPA_GROUP_TYPE_SHIFT)
171
172def add_l2_unfiltered_group(ctrl, ports, send_barrier=False, allow_vlan_translation=1):
173 # group table
174 # set up untag groups for each port
175 group_id_list=[]
176 msgs=[]
177 for of_port in ports:
178 # do stuff
179 group_id = encode_l2_unfiltered_group_id(of_port)
180 group_id_list.append(group_id)
181 actions = [ofp.action.output(of_port)]
182
183 actions.append(ofp.action.set_field(ofp.oxm.exp1ByteValue(exp_type=24, value=allow_vlan_translation)))
184 buckets = [ofp.bucket(actions=actions)]
185 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
186 group_id=group_id,
187 buckets=buckets
188 )
189 ctrl.message_send(request)
190 msgs.append(request)
191
192 if send_barrier:
193 do_barrier(ctrl)
194
195 return group_id_list, msgs
196
197def add_one_l2_unfiltered_group(ctrl, of_port, send_barrier=False):
198 # group table
199 # set up untag groups for each port
200 group_id = encode_l2_unfiltered_group_id(of_port)
201 actions = [ofp.action.output(of_port)]
202 actions.append(ofp.action.set_field(ofp.oxm.exp1ByteValue(exp_type=24, value=1)))
203
204 buckets = [ofp.bucket(actions=actions)]
205 request = ofp.message.group_add(
206 group_type=ofp.OFPGT_INDIRECT,
207 group_id=group_id,
208 buckets=buckets
209 )
210 ctrl.message_send(request)
211
212 if send_barrier:
213 do_barrier(ctrl)
214
215 return group_id, request
216
217def add_l2_interface_group(ctrl, ports, vlan_id=1, is_tagged=False, send_barrier=False):
218 # group table
219 # set up untag groups for each port
220 group_id_list=[]
221 msgs=[]
222 for of_port in ports:
223 # do stuff
224 group_id = encode_l2_interface_group_id(vlan_id, of_port)
225 group_id_list.append(group_id)
226 if is_tagged:
227 actions = [
228 ofp.action.output(of_port),
229 ]
230 else:
231 actions = [
232 ofp.action.pop_vlan(),
233 ofp.action.output(of_port),
234 ]
235
236 buckets = [
237 ofp.bucket(actions=actions),
238 ]
239
240 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
241 group_id=group_id,
242 buckets=buckets
243 )
244 ctrl.message_send(request)
245 msgs.append(request)
246
247 if send_barrier:
248 do_barrier(ctrl)
249
250 return group_id_list, msgs
251
252def add_one_l2_interface_group(ctrl, port, vlan_id=1, is_tagged=False, send_barrier=False):
253 # group table
254 # set up untag groups for each port
255 group_id = encode_l2_interface_group_id(vlan_id, port)
256
257 if is_tagged:
258 actions = [
259 ofp.action.output(port),
260 ]
261 else:
262 actions = [
263 ofp.action.pop_vlan(),
264 ofp.action.output(port),
265 ]
266
267 buckets = [
268 ofp.bucket(actions=actions),
269 ]
270
271 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
272 group_id=group_id,
273 buckets=buckets
274 )
275 ctrl.message_send(request)
276
277 if send_barrier:
278 do_barrier(ctrl)
279
280 return group_id, request
281
282def add_l2_mcast_group(ctrl, ports, vlanid, mcast_grp_index):
283 buckets=[]
284 for of_port in ports:
285 group_id = encode_l2_interface_group_id(vlanid, of_port)
286 action=[ofp.action.group(group_id)]
287 buckets.append(ofp.bucket(actions=action))
288
289 group_id =encode_l2_mcast_group_id(vlanid, mcast_grp_index)
290 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
291 group_id=group_id,
292 buckets=buckets
293 )
294 ctrl.message_send(request)
295 return request
296
297def add_l2_flood_group(ctrl, ports, vlanid, id):
298 buckets=[]
299 for of_port in ports:
300 group_id = encode_l2_interface_group_id(vlanid, of_port)
301 action=[ofp.action.group(group_id)]
302 buckets.append(ofp.bucket(actions=action))
303
304 group_id =encode_l2_flood_group_id(vlanid, id)
305 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
306 group_id=group_id,
307 buckets=buckets
308 )
309 ctrl.message_send(request)
310 return request
311
312def add_l2_flood_group_with_gids(ctrl, gids, vlanid, id, send_barrier=False):
313 buckets=[]
314 for gid in gids:
315 action=[ofp.action.group(gid)]
316 buckets.append(ofp.bucket(actions=action))
317
318 group_id =encode_l2_flood_group_id(vlanid, id)
319 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
320 group_id=group_id,
321 buckets=buckets
322 )
323 ctrl.message_send(request)
324
325 if send_barrier:
326 do_barrier(ctrl)
327
328 return request
329
330def mod_l2_flood_group(ctrl, ports, vlanid, id):
331 buckets=[]
332 for of_port in ports:
333 group_id = encode_l2_interface_group_id(vlanid, of_port)
334 action=[ofp.action.group(group_id)]
335 buckets.append(ofp.bucket(actions=action))
336
337 group_id =encode_l2_flood_group_id(vlanid, id)
338 request = ofp.message.group_modify(group_type=ofp.OFPGT_ALL,
339 group_id=group_id,
340 buckets=buckets
341 )
342 ctrl.message_send(request)
343 return request
344
345
346def add_l2_rewrite_group(ctrl, port, vlanid, id, src_mac, dst_mac):
347 group_id = encode_l2_interface_group_id(vlanid, port)
348
349 action=[]
350 if src_mac is not None:
351 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
352
353 if dst_mac is not None:
354 action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
355
356 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlanid)))
357
358 action.append(ofp.action.group(group_id))
359
360 buckets = [ofp.bucket(actions=action)]
361
362 group_id =encode_l2_rewrite_group_id(id)
363 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
364 group_id=group_id,
365 buckets=buckets
366 )
367 ctrl.message_send(request)
368 return request
369
370def add_l3_unicast_group(ctrl, port, vlanid, id, src_mac, dst_mac, send_barrier=False, gid=None):
371
372 if (not gid):
373 group_id = encode_l2_interface_group_id(vlanid, port)
374 else:
375 group_id = gid
376
377 action=[]
378 if src_mac is not None:
379 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
380
381 if dst_mac is not None:
382 action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
383
384 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlanid)))
385
386 action.append(ofp.action.group(group_id))
387
388 buckets = [ofp.bucket(actions=action)]
389
390 group_id =encode_l3_unicast_group_id(id)
391 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
392 group_id=group_id,
393 buckets=buckets
394 )
395 ctrl.message_send(request)
396
397 if send_barrier:
398 do_barrier(ctrl)
399
400 return request
401
402def add_l3_interface_group(ctrl, port, vlanid, id, src_mac):
403 group_id = encode_l2_interface_group_id(vlanid, port)
404
405 action=[]
406 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
407 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlanid)))
408 action.append(ofp.action.group(group_id))
409
410 buckets = [ofp.bucket(actions=action)]
411
412 group_id =encode_l3_interface_group_id(id)
413 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
414 group_id=group_id,
415 buckets=buckets
416 )
417 ctrl.message_send(request)
418 return request
419
420
421def add_l2_loadbal_group(ctrl, id, l2_unfil_intf_groups, send_barrier=False):
422 buckets=[]
423 for group in l2_unfil_intf_groups:
424 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
425
426 group_id=encode_l2_loadbal_group_id(id)
427 request = ofp.message.group_add(group_type=ofp.OFPGT_SELECT,
428 group_id=group_id,
429 buckets=buckets
430 )
431 ctrl.message_send(request)
432 if send_barrier:
433 do_barrier(ctrl)
434
435 return group_id, request
436
437def mod_l2_loadbal_group(ctrl, id, l2_unfil_intf_groups, send_barrier=False):
438 buckets=[]
439 for group in l2_unfil_intf_groups:
440 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
441
442 group_id =encode_l2_loadbal_group_id(id)
443 request = ofp.message.group_modify(group_type=ofp.OFPGT_SELECT,
444 group_id=group_id,
445 buckets=buckets
446 )
447 ctrl.message_send(request)
448 return request
449
450
451def add_l3_ecmp_group(ctrl, id, l3_ucast_groups, send_barrier=False):
452 buckets=[]
453 for group in l3_ucast_groups:
454 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
455
456 group_id =encode_l3_ecmp_group_id(id)
457 request = ofp.message.group_add(group_type=ofp.OFPGT_SELECT,
458 group_id=group_id,
459 buckets=buckets
460 )
461 ctrl.message_send(request)
462
463 if send_barrier:
464 do_barrier(ctrl)
465
466 return request
467
468def mod_l3_ecmp_group(ctrl, id, l3_ucast_groups):
469 buckets=[]
470 for group in l3_ucast_groups:
471 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
472
473 group_id =encode_l3_ecmp_group_id(id)
474 request = ofp.message.group_modify(group_type=ofp.OFPGT_SELECT,
475 group_id=group_id,
476 buckets=buckets
477 )
478 ctrl.message_send(request)
479 return request
480
481def add_l3_mcast_group(ctrl, vid, mcast_group_id, groups_on_buckets):
482 buckets=[]
483 for group in groups_on_buckets:
484 buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
485
486 group_id =encode_l3_mcast_group_id(vid, mcast_group_id)
487 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
488 group_id=group_id,
489 buckets=buckets
490 )
491 ctrl.message_send(request)
492 return request
493
494def add_l2_overlay_flood_over_unicast_tunnel_group(ctrl, tunnel_id, ports, index):
495 buckets=[]
496 for port in ports:
497 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
498
499 group_id=encode_l2_overlay_group_id(tunnel_id, 0, index)
500 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
501 group_id=group_id,
502 buckets=buckets
503 )
504 ctrl.message_send(request)
505 return request
506
507def add_l2_overlay_flood_over_mcast_tunnel_group(ctrl, tunnel_id, ports, index):
508 buckets=[]
509 for port in ports:
510 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
511
512 group_id=encode_l2_overlay_group_id(tunnel_id, 1, index)
513 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
514 group_id=group_id,
515 buckets=buckets
516 )
517 ctrl.message_send(request)
518 return request
519
520def add_l2_overlay_mcast_over_unicast_tunnel_group(ctrl, tunnel_id, ports, index):
521 buckets=[]
522 for port in ports:
523 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
524
525 group_id=encode_l2_overlay_group_id(tunnel_id, 2, index)
526 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
527 group_id=group_id,
528 buckets=buckets
529 )
530 ctrl.message_send(request)
531 return request
532
533def add_l2_overlay_mcast_over_mcast_tunnel_group(ctrl, tunnel_id, ports, index):
534 buckets=[]
535 for port in ports:
536 buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
537
538 group_id=encode_l2_overlay_group_id(tunnel_id, 3, index)
539 request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
540 group_id=group_id,
541 buckets=buckets
542 )
543 ctrl.message_send(request)
544 return request
545
546def add_port_table_flow(ctrl, is_overlay=True):
547 match = ofp.match()
548
549 if is_overlay == True:
550 match.oxm_list.append(ofp.oxm.in_port(0x10000))
551 NEXT_TABLE=50
552 else:
553 match.oxm_list.append(ofp.oxm.in_port(0))
554 NEXT_TABLE=10
555
556 request = ofp.message.flow_add(
557 table_id=0,
558 cookie=42,
559 match=match,
560 instructions=[
561 ofp.instruction.goto_table(NEXT_TABLE)
562 ],
563 priority=0)
564 logging.info("Add port table, match port %lx" % 0x10000)
565 ctrl.message_send(request)
566
567def pop_vlan_flow(ctrl, ports, vlan_id=1):
568 # table 10: vlan
569 # goto to table 20
570 msgs=[]
571 for of_port in ports:
572 match = ofp.match()
573 match.oxm_list.append(ofp.oxm.in_port(of_port))
574 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
575 request = ofp.message.flow_add(
576 table_id=10,
577 cookie=42,
578 match=match,
579 instructions=[
580 ofp.instruction.apply_actions(
581 actions=[
582 ofp.action.pop_vlan()
583 ]
584 ),
585 ofp.instruction.goto_table(20)
586 ],
587 priority=0)
588 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
589 ctrl.message_send(request)
590
591
592 return msgs
593
594def add_vlan_table_flow(ctrl, ports, vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
595 # table 10: vlan
596 # goto to table 20
597 msgs=[]
598 for of_port in ports:
599 if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH) or (flag == 4):
600 match = ofp.match()
601 match.oxm_list.append(ofp.oxm.in_port(of_port))
602 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
603 request = ofp.message.flow_add(
604 table_id=10,
605 cookie=42,
606 match=match,
607 instructions=[
608 ofp.instruction.apply_actions(
609 actions=[
610 ofp.action.pop_vlan()
611 ]
612 ),
613 ofp.instruction.goto_table(20)
614 ],
615 priority=0)
616 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
617 ctrl.message_send(request)
618
619 if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
620 match = ofp.match()
621 match.oxm_list.append(ofp.oxm.in_port(of_port))
622 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0, 0x1fff))
623 request = ofp.message.flow_add(
624 table_id=10,
625 cookie=42,
626 match=match,
627 instructions=[
628 ofp.instruction.apply_actions(
629 actions=[
630 ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id))
631 ]
632 ),
633 ofp.instruction.goto_table(20)
634 ],
635 priority=0)
636 logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
637 ctrl.message_send(request)
638 msgs.append(request)
639
640 if (flag == 4) :
641 match = ofp.match()
642 match.oxm_list.append(ofp.oxm.in_port(of_port))
643 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000, 0x1fff))
644 request = ofp.message.flow_add(
645 table_id=10,
646 cookie=42,
647 match=match,
648 instructions=[
649 ofp.instruction.apply_actions(
650 actions=[
651 ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id))
652 ]
653 ),
654 ofp.instruction.goto_table(20)
655 ],
656 priority=0)
657 logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
658 ctrl.message_send(request)
659 msgs.append(request)
660
661 if send_barrier:
662 do_barrier(ctrl)
663
664 return msgs
665
666def del_vlan_table_flow(ctrl, ports, vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
667 # table 10: vlan
668 # goto to table 20
669 msgs=[]
670 for of_port in ports:
671 if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
672 match = ofp.match()
673 match.oxm_list.append(ofp.oxm.in_port(of_port))
674 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
675 request = ofp.message.flow_delete(
676 table_id=10,
677 cookie=42,
678 match=match,
679 priority=0)
680 logging.info("Del vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
681 ctrl.message_send(request)
682
683 if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
684 match = ofp.match()
685 match.oxm_list.append(ofp.oxm.in_port(of_port))
686 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0, 0xfff))
687 request = ofp.message.flow_delete(
688 table_id=10,
689 cookie=42,
690 match=match,
691 priority=0)
692 logging.info("Del vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
693 ctrl.message_send(request)
694 msgs.append(request)
695
696 if send_barrier:
697 do_barrier(ctrl)
698
699 return msgs
700
701def add_vlan_table_flow_pvid(ctrl, in_port, match_vid=None, pvid=1, send_barrier=False):
702 """it will tag pack as untagged packet wether it has tagg or not"""
703 match = ofp.match()
704 match.oxm_list.append(ofp.oxm.in_port(in_port))
705 actions=[]
706 if match_vid == None:
707 match.oxm_list.append(ofp.oxm.vlan_vid(0))
708 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+pvid)))
709 goto_table=20
710 else:
711 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+match_vid, 0x1fff))
712 actions.append(ofp.action.push_vlan(0x8100))
713 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+pvid)))
714 goto_table=20
715
716 request = ofp.message.flow_add(
717 table_id=10,
718 cookie=42,
719 match=match,
720 instructions=[
721 ofp.instruction.apply_actions(actions=actions)
722 ,ofp.instruction.goto_table(goto_table)
723 ],
724 priority=0)
725 logging.info("Add PVID %d on port %d and go to table %ld" %( pvid, in_port, goto_table))
726 ctrl.message_send(request)
727
728 if send_barrier:
729 do_barrier(ctrl)
730
731def add_vlan_table_flow_allow_all_vlan(ctrl, in_port, send_barrier=False):
732 """it st flow allow all vlan tag on this port"""
733 match = ofp.match()
734 match.oxm_list.append(ofp.oxm.in_port(in_port))
735 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000, 0x1000))
736 request = ofp.message.flow_add(
737 table_id=10,
738 cookie=42,
739 match=match,
740 instructions=[
741 ofp.instruction.goto_table(20)
742 ],
743 priority=0)
744 logging.info("Add allow all vlan on port %d " %(in_port))
745 ctrl.message_send(request)
746
747def add_one_vlan_table_flow_translation(ctrl, of_port, vlan_id=1, new_vlan_id=-1, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
748 # Install a flow for VLAN translation
749 # in VLAN table.
750 # table 10: vlan
751 # goto to table 20
752 if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH) or (flag == 4):
753 match = ofp.match()
754 match.oxm_list.append(ofp.oxm.in_port(of_port))
755 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id,0x1fff))
756
757 actions=[]
758 if vrf!=0:
759 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
760 if new_vlan_id != -1:
761 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_vlan_id)))
762
763 request = ofp.message.flow_add(
764 table_id=10,
765 cookie=42,
766 match=match,
767 instructions=[
768 ofp.instruction.apply_actions(
769 actions=actions
770 ),
771 ofp.instruction.goto_table(20)
772 ],
773 priority=0)
774 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
775 ctrl.message_send(request)
776
777
778def add_one_egress_vlan_table_flow(ctrl, of_port, match_vlan, inner_vlan, outer_vlan):
779
780 # used for translating single to double tagged packets only
781
782 match = ofp.match()
783 match.oxm_list.append(ofp.oxm.exp4ByteValue(ofp.oxm.OFDPA_EXP_TYPE_ACTSET_OUTPUT, of_port))
784 match.oxm_list.append(ofp.oxm.exp1ByteValue(ofp.oxm.OFDPA_EXP_TYPE_ALLOW_VLAN_TRANSLATION, 1))
785 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+match_vlan,0x1fff))
786
787 actions=[]
788 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+inner_vlan)))
789 actions.append(ofp.action.push_vlan(0x8100))
790 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+outer_vlan)))
791
792 request = ofp.message.flow_add(
793 table_id=EGRESS_VLAN_FLOW_TABLE,
794 cookie=42,
795 match=match,
796 instructions=[
797 ofp.instruction.apply_actions(
798 actions=actions
799 ),
800 ofp.instruction.goto_table(EGRESS_DSCP_TABLE)
801 ],
802 priority=0)
803
804 ctrl.message_send(request)
805
806 return
807
808def add_one_vlan_table_flow(ctrl, of_port, out_vlan_id=1, vlan_id=1, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
809
810 # goto to table 20
811 if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH) or (flag == 4):
812 match = ofp.match()
813 match.oxm_list.append(ofp.oxm.in_port(of_port))
814 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id,0x1fff))
815
816 actions=[]
817 if config["switch_type"] != 'xpliant' and vrf != 0:
818 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
819
820 #actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(value=vlan_id)))
821
822 request = ofp.message.flow_add(
823 table_id=10,
824 cookie=42,
825 match=match,
826 instructions=[
827 ofp.instruction.apply_actions(
828 actions=actions
829 ),
830 ofp.instruction.goto_table(20)
831 ],
832 priority=0)
833 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
834 ctrl.message_send(request)
835
836 if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
837
838 match = ofp.match()
839 match.oxm_list.append(ofp.oxm.in_port(of_port))
840 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0, 0x1fff))
841
842 actions=[]
843 if vrf!=0:
844 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
845
846 # actions.append(ofp.action.push_vlan(0x8100))
847 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
848
849 request = ofp.message.flow_add(
850 table_id=10,
851 cookie=42,
852 match=match,
853 instructions=[
854 ofp.instruction.apply_actions(
855 actions=actions
856 ),
857 ofp.instruction.goto_table(20)
858 ],
859 priority=0)
860 logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
861 ctrl.message_send(request)
862
863 if (flag == 4) :
864 match = ofp.match()
865 match.oxm_list.append(ofp.oxm.in_port(of_port))
866 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000,0x1fff))
867
868 actions=[]
869 if vrf!=0:
870 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
871
872 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
873
874 request = ofp.message.flow_add(
875 table_id=10,
876 cookie=42,
877 match=match,
878 instructions=[
879 ofp.instruction.apply_actions(
880 actions=actions
881 ),
882 ofp.instruction.goto_table(20)
883 ],
884 priority=0)
885 logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
886 ctrl.message_send(request)
887
888 if (flag == VLAN_TABLE_FLAG_ONLY_STACKED):
889 # This flag is meant to managed stacked vlan packtes
890 # Matches on outer VLAN_ID, set OVID with outer VLAN.
891 # Finally expose inner VLAN_ID with a pop action and
892 # goto VLAN_1_FLOW_TABLE
893 match = ofp.match()
894 match.oxm_list.append(ofp.oxm.in_port(of_port))
895 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id,0x1fff))
896
897 actions=[]
898 # actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_OVID, value=0x1000+vlan_id)))
899 actions.append(ofp.action.pop_vlan())
900 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_OVID, value=0x1000+vlan_id)))
901
902 request = ofp.message.flow_add(
903 table_id=10,
904 cookie=42,
905 match=match,
906 instructions=[
907 ofp.instruction.apply_actions(
908 actions=actions
909 ),
910 ofp.instruction.goto_table(VLAN_1_FLOW_TABLE)
911 ],
912 priority=0)
913 logging.info("Add vlan %d tagged packets on port %d and go to table %d" %( vlan_id, of_port, VLAN_1_FLOW_TABLE))
914 ctrl.message_send(request)
915
916 if (flag == VLAN_TABLE_FLAG_PRIORITY) :
917 match = ofp.match()
918 match.oxm_list.append(ofp.oxm.in_port(of_port))
919 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000, 0x1fff))
920 request = ofp.message.flow_add(
921 table_id=10,
922 cookie=42,
923 match=match,
924 instructions=[
925 ofp.instruction.apply_actions(
926 actions=[
927 ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)),
928 ofp.action.push_vlan(0x8100),
929 ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+out_vlan_id)),
930 ]
931 ),
932 ofp.instruction.goto_table(20)
933 ],
934 priority=0)
935 logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
936 ctrl.message_send(request)
937
938 if send_barrier:
939 do_barrier(ctrl)
940
941 return request
942
943def add_one_vlan_table_flow_pw(ctrl, of_port, tunnel_index, new_vlan_id=1, vlan_id=1, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_TAG, send_barrier=False):
944 # table 10: vlan
945 # goto to table 13
946 if flag == VLAN_TABLE_FLAG_ONLY_TAG:
947 match = ofp.match()
948 match.oxm_list.append(ofp.oxm.in_port(of_port))
949 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id, 0x1fff))
950
951 actions=[]
952 if vlan_id == -1:
953 actions.append(ofp.action.pop_vlan())
954 if new_vlan_id > 1:
955 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_vlan_id)))
956 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
957 actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
958 # 0x0000nnnn is for UNI interfaces
959 actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port)))
960
961 request = ofp.message.flow_add(
962 table_id=10,
963 cookie=42,
964 match=match,
965 instructions=[
966 ofp.instruction.apply_actions(
967 actions=actions
968 ),
969 ofp.instruction.goto_table(MPLS_L2_PORT_FLOW_TABLE)
970 ],
971 priority=0)
972 logging.info("Add vlan %d tagged packets on port %d and go to table %d" % (vlan_id, of_port, MPLS_L2_PORT_FLOW_TABLE))
973 ctrl.message_send(request)
974
975 if flag == VLAN_TABLE_FLAG_ONLY_UNTAG:
976 match = ofp.match()
977 match.oxm_list.append(ofp.oxm.in_port(of_port))
978 match.oxm_list.append(ofp.oxm.vlan_vid(0))
979
980 actions=[]
981 if vlan_id > 1:
982 # actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
983 # actions.append(ofp.action.set_field(ofp.action.push_vlan(0x8100)))
984 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
985
986 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
987 actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
988 # 0x0000nnnn is for UNI interfaces
989 actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port)))
990
991 request = ofp.message.flow_add(
992 table_id=10,
993 cookie=42,
994 match=match,
995 instructions=[
996 ofp.instruction.apply_actions(
997 actions=actions
998 ),
999 ofp.instruction.goto_table(MPLS_L2_PORT_FLOW_TABLE)
1000 ],
1001 priority=0)
1002 logging.info("Add vlan %d untagged packets on port %d and go to table %d" % (vlan_id, of_port, MPLS_L2_PORT_FLOW_TABLE))
1003 ctrl.message_send(request)
1004
1005 if send_barrier:
1006 do_barrier(ctrl)
1007
1008 return request
1009
1010def add_one_vlan_1_table_flow(ctrl, of_port, new_outer_vlan_id=-1, outer_vlan_id=1, inner_vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_TAG, send_barrier=False):
1011
1012 # table 11: vlan 1 table
1013 # goto to table 20
1014 if flag == VLAN_TABLE_FLAG_ONLY_TAG:
1015 match = ofp.match()
1016 match.oxm_list.append(ofp.oxm.in_port(of_port))
1017 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
1018 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
1019
1020 actions=[]
1021 actions.append(ofp.action.push_vlan(0x8100))
1022 if new_outer_vlan_id != -1:
1023 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_outer_vlan_id)))
1024 else:
1025 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+outer_vlan_id)))
1026
1027 request = ofp.message.flow_add(
1028 table_id=11,
1029 cookie=42,
1030 match=match,
1031 instructions=[
1032 ofp.instruction.apply_actions(
1033 actions=actions
1034 ),
1035 ofp.instruction.goto_table(TERMINATION_FLOW_TABLE)
1036 ],
1037 priority=0)
1038 logging.info("Add vlan 1 double tagged %d-%d packets on port %d and go to table %d" %( outer_vlan_id, inner_vlan_id, of_port, TERMINATION_FLOW_TABLE))
1039 ctrl.message_send(request)
1040
1041 if flag == VLAN_TABLE_FLAG_ONLY_UNTAG:
1042
1043 match = ofp.match()
1044 match.oxm_list.append(ofp.oxm.in_port(of_port))
1045 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
1046 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
1047
1048 actions=[]
1049 request = ofp.message.flow_add(
1050 table_id=11,
1051 cookie=42,
1052 match=match,
1053 instructions=[
1054 ofp.instruction.apply_actions(
1055 actions=actions
1056 ),
1057 ofp.instruction.goto_table(TERMINATION_FLOW_TABLE)
1058 ],
1059 priority=0)
1060 logging.info("Add vlan 1 double tagged %d-%d packets on port %d and go to table %d" %( outer_vlan_id, inner_vlan_id, of_port, TERMINATION_FLOW_TABLE))
1061 ctrl.message_send(request)
1062
1063 if flag == VLAN_TABLE_FLAG_ONLY_POP_VLAN:
1064
1065 print("INSTALLIN IN TABLE 11!")
1066
1067 match = ofp.match()
1068 match.oxm_list.append(ofp.oxm.in_port(of_port))
1069 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
1070 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
1071
1072 actions=[]
1073 actions.append(ofp.action.pop_vlan())
1074
1075 request = ofp.message.flow_add(
1076 table_id=11,
1077 cookie=42,
1078 match=match,
1079 instructions=[
1080 ofp.instruction.apply_actions(
1081 actions=actions
1082 ),
1083 ofp.instruction.goto_table(TERMINATION_FLOW_TABLE)
1084 ],
1085 priority=0)
1086 logging.info("Add vlan 1 double tagged %d-%d packets on port %d and go to table %d" %( outer_vlan_id, inner_vlan_id, of_port, TERMINATION_FLOW_TABLE))
1087 ctrl.message_send(request)
1088
1089
1090 if send_barrier:
1091 do_barrier(ctrl)
1092
1093 return request
1094
1095def add_one_vlan_1_table_flow_pw(ctrl, of_port, tunnel_index, new_outer_vlan_id=-1, outer_vlan_id=1, inner_vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_TAG, cross_connect=False, send_barrier=False):
1096
1097 # table 11: vlan 1 table
1098 # goto to table 13
1099 match = ofp.match()
1100 match.oxm_list.append(ofp.oxm.in_port(of_port))
1101 match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
1102 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
1103
1104 actions=[]
1105
1106 if cross_connect:
1107 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+inner_vlan_id)))
1108 actions.append(ofp.action.push_vlan(0x8100))
1109 if new_outer_vlan_id != -1:
1110 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_outer_vlan_id)))
1111 else:
1112 actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+outer_vlan_id)))
1113
1114 if not cross_connect:
1115 actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
1116 actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
1117 else:
1118 actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE_CROSS_CONNECT)))
1119
1120 # 0x0000nnnn is for UNI interfaces
1121 actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port)))
1122
1123 request = ofp.message.flow_add(
1124 table_id=11,
1125 cookie=42,
1126 match=match,
1127 instructions=[
1128 ofp.instruction.apply_actions(
1129 actions=actions
1130 ),
1131 ofp.instruction.goto_table(MPLS_L2_PORT_FLOW_TABLE)
1132 ],
1133 priority=0)
1134 logging.info("Add vlan 1 double tagged %d-%d packets on port %d and go to table %d" %( outer_vlan_id, inner_vlan_id, of_port, MPLS_L2_PORT_FLOW_TABLE))
1135 ctrl.message_send(request)
1136 if send_barrier:
1137 do_barrier(ctrl)
1138
1139 return request
1140
1141def add_bridge_flow(ctrl, dst_mac, vlanid, group_id, send_barrier=False):
1142 match = ofp.match()
1143 priority=500
1144 if dst_mac!=None:
1145 priority=1000
1146 match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
1147
1148 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
1149
1150 request = ofp.message.flow_add(
1151 table_id=50,
1152 cookie=42,
1153 match=match,
1154 instructions=[
1155 ofp.instruction.write_actions(
1156 actions=[
1157 ofp.action.group(group_id)]),
1158 ofp.instruction.goto_table(60)
1159 ],
1160 buffer_id=ofp.OFP_NO_BUFFER,
1161 priority=priority)
1162
1163 logging.info("Inserting Brdige flow vlan %d, mac %s", vlanid, dst_mac)
1164 ctrl.message_send(request)
1165
1166 if send_barrier:
1167 do_barrier(ctrl)
1168
1169 return request
1170
1171def add_overlay_bridge_flow(ctrl, dst_mac, vnid, group_id, is_group=True, send_barrier=False):
1172 match = ofp.match()
1173 if dst_mac!=None:
1174 match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
1175
1176 match.oxm_list.append(ofp.oxm.tunnel_id(vnid))
1177 if is_group == True:
1178 actions=[ofp.action.group(group_id)]
1179 else:
1180 actions=[ofp.action.output(group_id)]
1181
1182 request = ofp.message.flow_add(
1183 table_id=50,
1184 cookie=42,
1185 match=match,
1186 instructions=[
1187 ofp.instruction.write_actions(
1188 actions=actions),
1189 ofp.instruction.goto_table(60)
1190 ],
1191 buffer_id=ofp.OFP_NO_BUFFER,
1192 priority=1000)
1193
1194 logging.info("Inserting Brdige flow vnid %d, mac %s", vnid, dst_mac)
1195 ctrl.message_send(request)
1196
1197 if send_barrier:
1198 do_barrier(ctrl)
1199
1200 return request
1201
1202def add_termination_flow(ctrl, in_port, eth_type, dst_mac, vlanid, goto_table=None, send_barrier=False):
1203 match = ofp.match()
1204 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1205 if dst_mac[0]&0x01 == 0x01:
1206 match.oxm_list.append(ofp.oxm.eth_dst_masked(dst_mac, [0xff, 0xff, 0xff, 0x80, 0x00, 0x00]))
1207 goto_table=40
1208 else:
1209 if in_port!=0:
1210 match.oxm_list.append(ofp.oxm.in_port(in_port))
1211 match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
1212 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
1213 if goto_table == None:
1214 goto_table=30
1215
1216 request = ofp.message.flow_add(
1217 table_id=20,
1218 cookie=42,
1219 match=match,
1220 instructions=[
1221 ofp.instruction.goto_table(goto_table)
1222 ],
1223 buffer_id=ofp.OFP_NO_BUFFER,
1224 priority=1)
1225
1226 logging.info("Inserting termination flow inport %d, eth_type %lx, vlan %d, mac %s", in_port, eth_type, vlanid, dst_mac)
1227 ctrl.message_send(request)
1228 if send_barrier:
1229 do_barrier(ctrl)
1230
1231 return request
1232
1233def add_unicast_routing_flow(ctrl, eth_type, dst_ip, mask, action_group_id, vrf=0, send_ctrl=False, send_barrier=False, priority = 1):
1234 match = ofp.match()
1235 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1236 if config["switch_type"] != 'xpliant' and vrf != 0:
1237 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
1238
1239 match.oxm_list.append(ofp.oxm.ipv4_dst_masked(dst_ip, mask))
1240
1241 instructions = []
1242 instructions.append(ofp.instruction.goto_table(60))
1243 if send_ctrl:
1244 instructions.append(ofp.instruction.write_actions(
1245 actions=[ofp.action.output( port=ofp.OFPP_CONTROLLER,
1246 max_len=ofp.OFPCML_NO_BUFFER)]))
1247 else:
1248 instructions.append(ofp.instruction.write_actions(
1249 actions=[ofp.action.group(action_group_id)]))
1250
1251 request = ofp.message.flow_add(
1252 table_id=30,
1253 cookie=42,
1254 match=match,
1255 instructions=instructions,
1256 buffer_id=ofp.OFP_NO_BUFFER,
1257 priority=priority)
1258
1259 logging.info("Inserting unicast routing flow eth_type %lx, dip %ld",eth_type, dst_ip)
1260 ctrl.message_send(request)
1261
1262 if send_barrier:
1263 do_barrier(ctrl)
1264
1265 return request
1266
1267def add_unicast_blackhole_flow(ctrl, eth_type, dst_ip, mask, vrf=0, send_ctrl=False, send_barrier=False, priority = 1):
1268 match = ofp.match()
1269 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1270 if config["switch_type"] != 'xpliant' and vrf != 0:
1271 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
1272
1273 match.oxm_list.append(ofp.oxm.ipv4_dst_masked(dst_ip, mask))
1274
1275 instructions = []
1276 instructions.append(ofp.instruction.goto_table(60))
1277 instructions.append(ofp.instruction.clear_actions( ))
1278
1279 request = ofp.message.flow_add(
1280 table_id=30,
1281 cookie=42,
1282 match=match,
1283 instructions=instructions,
1284 buffer_id=ofp.OFP_NO_BUFFER,
1285 priority=priority)
1286
1287 logging.info("Inserting unicast blackhole routing flow eth_type %lx, dip %ld",eth_type, dst_ip)
1288 ctrl.message_send(request)
1289
1290 if send_barrier:
1291 do_barrier(ctrl)
1292
1293 return request
1294
1295def add_unicast_v6_routing_flow(ctrl, eth_type, dst_ip, mask, action_group_id, vrf=0, send_ctrl=False, send_barrier=False):
1296 match = ofp.match()
1297 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1298 if vrf != 0:
1299 match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
1300
1301 match.oxm_list.append(ofp.oxm.ipv6_dst_masked(parse_ipv6(dst_ip), parse_ipv6(mask)))
1302
1303 instructions = []
1304 instructions.append(ofp.instruction.goto_table(60))
1305 if send_ctrl:
1306 instructions.append(ofp.instruction.write_actions(
1307 actions=[ofp.action.output( port=ofp.OFPP_CONTROLLER,
1308 max_len=ofp.OFPCML_NO_BUFFER)]))
1309 else:
1310 instructions.append(ofp.instruction.write_actions(
1311 actions=[ofp.action.group(action_group_id)]))
1312
1313 request = ofp.message.flow_add(
1314 table_id=30,
1315 cookie=42,
1316 match=match,
1317 instructions=instructions,
1318 buffer_id=ofp.OFP_NO_BUFFER,
1319 priority=1)
1320
1321 logging.info("Inserting unicast routing flow eth_type %lx, dip %s",eth_type, dst_ip)
1322 ctrl.message_send(request)
1323
1324 if send_barrier:
1325 do_barrier(ctrl)
1326
1327 return request
1328
1329def add_mpls_flow(ctrl, action_group_id=0x0, label=100 ,ethertype=0x0800, bos=1, vrf=1, goto_table=27, dec_ttl=False, send_barrier=False):
1330 match = ofp.match()
1331 match.oxm_list.append(ofp.oxm.eth_type(0x8847))
1332 match.oxm_list.append(ofp.oxm.mpls_label(label))
1333 match.oxm_list.append(ofp.oxm.mpls_bos(bos))
1334 write_actions = []
1335 write_actions.append(ofp.action.group(action_group_id))
1336 apply_actions = []
1337 apply_actions = [ofp.action.dec_mpls_ttl(),
1338 ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf))]
1339 if (goto_table != 29):
1340 apply_actions.append(ofp.action.set_field(
1341 ofp.oxm.exp2ByteValue(exp_type=23, value=32)))
1342 apply_actions.append(ofp.action.copy_ttl_in())
1343
1344 request = ofp.message.flow_add(
1345 table_id=24,
1346 cookie=43,
1347 match=match,
1348 instructions=[
1349 ofp.instruction.apply_actions(actions=apply_actions),
1350 ofp.instruction.write_actions(actions=write_actions),
1351 ofp.instruction.goto_table(goto_table)
1352 ],
1353 buffer_id=ofp.OFP_NO_BUFFER,
1354 priority=1)
1355 ctrl.message_send(request)
1356
1357 if send_barrier:
1358 do_barrier(ctrl)
1359
1360 return request
1361
1362def xpliant_add_mpls_flow(ctrl, action_group_id=0x0, label=100 ,ethertype=0x0800, bos=1, vrf=1, goto_table=27, send_barrier=False):
1363 match = ofp.match()
1364 match.oxm_list.append(ofp.oxm.eth_type(0x8847))
1365 match.oxm_list.append(ofp.oxm.mpls_label(label))
1366
1367 apply_actions = []
1368 apply_actions.append(ofp.action.group(action_group_id))
1369 apply_actions.append(ofp.action.dec_mpls_ttl())
1370 if (goto_table != 29):
1371 apply_actions.append(ofp.action.pop_mpls(ethertype))
1372
1373 request = ofp.message.flow_add(
1374 table_id=24,
1375 cookie=43,
1376 match=match,
1377 instructions=[
1378 ofp.instruction.apply_actions(actions=apply_actions),
1379 ],
1380 buffer_id=ofp.OFP_NO_BUFFER,
1381 priority=1)
1382 logging.info("Inserting MPLS flow , label %ld", label)
1383 ctrl.message_send(request)
1384
1385 if send_barrier:
1386 do_barrier(ctrl)
1387
1388 return request
1389
1390def add_mpls_flow_swap(ctrl, action_group_id, label, ethertype, bos, goto_table=MPLS_TYPE_FLOW_TABLE, of_port=0, send_barrier=False):
1391 match = ofp.match()
1392 match.oxm_list.append(ofp.oxm.eth_type(0x8847))
1393 match.oxm_list.append(ofp.oxm.mpls_label(label))
1394 match.oxm_list.append(ofp.oxm.mpls_bos(1))
1395
1396 apply_actions = []
1397 write_actions = []
1398 apply_actions.append(ofp.action.dec_mpls_ttl())
1399 write_actions.append(ofp.action.group(action_group_id))
1400
1401 request = ofp.message.flow_add(
1402 table_id=24,
1403 cookie=43,
1404 match=match,
1405 instructions=[
1406 ofp.instruction.apply_actions(actions=apply_actions),
1407 ofp.instruction.write_actions(actions=write_actions),
1408 ofp.instruction.goto_table(goto_table)
1409 ],
1410 buffer_id=ofp.OFP_NO_BUFFER,
1411 priority=1)
1412
1413 logging.info("Inserting MPLS flow , label %ld", label)
1414 ctrl.message_send(request)
1415
1416 if send_barrier:
1417 do_barrier(ctrl)
1418
1419 return request
1420
1421
1422def add_mpls_flow_pw(ctrl, action_group_id, label, ethertype, bos, tunnel_index, goto_table=MPLS_TYPE_FLOW_TABLE, popMPLS=True, popL2=False, of_port=0, send_barrier=False):
1423 match = ofp.match()
1424 match.oxm_list.append(ofp.oxm.eth_type(0x8847))
1425 match.oxm_list.append(ofp.oxm.mpls_label(label))
1426 match.oxm_list.append(ofp.oxm.mpls_bos(bos))
1427
1428 apply_actions = []
1429 write_actions = []
1430 apply_actions.append(ofp.action.dec_mpls_ttl())
1431 if popMPLS == True:
1432 apply_actions.append(ofp.action.copy_ttl_in())
1433 apply_actions.append(ofp.action.pop_mpls(ethertype))
1434 if bos==1 and popL2 == True:
1435 apply_actions.append(ofp.action.ofdpa_pop_l2_header())
1436 apply_actions.append(ofp.action.ofdpa_pop_cw())
1437 apply_actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
1438 # 0x0002nnnn is for UNI interfaces
1439 apply_actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00020000 + of_port)))
1440 apply_actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
1441
1442 write_actions.append(ofp.action.group(action_group_id))
1443
1444 request = ofp.message.flow_add(
1445 table_id=24,
1446 cookie=43,
1447 match=match,
1448 instructions=[
1449 ofp.instruction.apply_actions(actions=apply_actions),
1450 ofp.instruction.write_actions(actions=write_actions),
1451 ofp.instruction.goto_table(goto_table)
1452 ],
1453 buffer_id=ofp.OFP_NO_BUFFER,
1454 priority=1)
1455 logging.info("Inserting MPLS flow , label %ld", label)
1456 ctrl.message_send(request)
1457
1458 if send_barrier:
1459 do_barrier(ctrl)
1460
1461 return request
1462
1463def add_mcast4_routing_flow(ctrl, vlan_id, src_ip, src_ip_mask, dst_ip, action_group_id, send_barrier=False):
1464 match = ofp.match()
1465 match.oxm_list.append(ofp.oxm.eth_type(0x0800))
1466 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000 + vlan_id))
1467 if src_ip_mask!=0:
1468 match.oxm_list.append(ofp.oxm.ipv4_src_masked(src_ip, src_ip_mask))
1469 else:
1470 match.oxm_list.append(ofp.oxm.ipv4_src(src_ip))
1471
1472 match.oxm_list.append(ofp.oxm.ipv4_dst(dst_ip))
1473
1474 request = ofp.message.flow_add(
1475 table_id=40,
1476 cookie=42,
1477 match=match,
1478 instructions=[
1479 ofp.instruction.write_actions(
1480 actions=[ofp.action.group(action_group_id)]),
1481 ofp.instruction.goto_table(60)
1482 ],
1483 buffer_id=ofp.OFP_NO_BUFFER,
1484 priority=1)
1485
1486 logging.info("Inserting mcast routing flow eth_type %lx, dip %lx, sip %lx, sip_mask %lx",0x0800, dst_ip, src_ip, src_ip_mask)
1487 ctrl.message_send(request)
1488
1489 if send_barrier:
1490 do_barrier(ctrl)
1491
1492 return request
1493
1494def add_acl_rule(ctrl, eth_type=None, ip_proto=None, vlan_id=None, send_barrier=False):
1495 match = ofp.match()
1496 if eth_type:
1497 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1498 if ip_proto:
1499 match.oxm_list.append(ofp.oxm.ip_proto(ip_proto))
1500 if vlan_id:
1501 match.oxm_list.append(ofp.oxm.vlan_vid(0x1000 + vlan_id))
1502 request = ofp.message.flow_add(
1503 table_id=60,
1504 cookie=42,
1505 match=match,
1506 instructions=[
1507 ofp.instruction.apply_actions(
1508 actions=[ofp.action.output(port=ofp.OFPP_CONTROLLER, max_len=ofp.OFPCML_NO_BUFFER)]
1509 ),
1510 ],
1511 buffer_id=ofp.OFP_NO_BUFFER,
1512 priority=1
1513 )
1514 output = "Inserting ACL flow: "
1515 if eth_type:
1516 output += "eth_type {}, ".format(eth_type)
1517 if ip_proto:
1518 output += "ip_proto {}, ".format(ip_proto)
1519 if vlan_id:
1520 output += "vlan_id {}".format(vlan_id)
1521 logging.info(output)
1522
1523 ctrl.message_send(request)
1524
1525 if send_barrier:
1526 do_barrier(ctrl)
1527
1528 return request
1529
1530#dpctl tcp:192.168.1.1:6633 flow-mod table=28,cmd=add,prio=281 eth_type=0x800,ip_dst=100.0.0.1,ip_proto=6,tcp_dst=5000 write:set_field=ip_dst:10.0.0.1,set_field=tcp_dst:2000,group=0x71000001 goto:60
1531def add_dnat_flow(ctrl, eth_type, ip_dst, ip_proto, tcp_dst, set_ip_dst, set_tcp_dst, action_group_id):
1532 match = ofp.match()
1533 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1534 match.oxm_list.append(ofp.oxm.ipv4_dst(ip_dst))
1535 match.oxm_list.append(ofp.oxm.ip_proto(ip_proto))
1536 match.oxm_list.append(ofp.oxm.tcp_dst(tcp_dst))
1537
1538 request = ofp.message.flow_add(
1539 table_id=28,
1540 cookie=42,
1541 match=match,
1542 instructions=[
1543 ofp.instruction.write_actions(
1544 actions=[ofp.action.set_field(ofp.oxm.ipv4_dst(set_ip_dst)),
1545 ofp.action.set_field(ofp.oxm.tcp_dst(set_tcp_dst)),
1546 ofp.action.group(action_group_id)]),
1547 ofp.instruction.goto_table(60)
1548 ],
1549 buffer_id=ofp.OFP_NO_BUFFER,
1550 priority=1)
1551 logging.info("Inserting DNAT flow eth_type %lx, dip %lx, ip_proto %ld, tcp_dst %ld, SetFeild: Dip %lx, tcp_dst %ld, action_gorup=%lx",eth_type, ip_dst, ip_proto, tcp_dst, set_ip_dst, set_tcp_dst, action_group_id)
1552 ctrl.message_send(request)
1553 return request
1554
1555#dpctl tcp:192.168.1.1:6633 flow-mod table=29,cmd=add,prio=291 eth_type=0x800,ip_src=10.0.0.1,ip_proto=6,tcp_src=2000 write:set_field=ip_src:100.0.0.1,set_field=tcp_src:5000 goto:30
1556def add_snat_flow(ctrl, eth_type, ip_src, ip_proto, tcp_src, set_ip_src, set_tcp_src):
1557 match = ofp.match()
1558 match.oxm_list.append(ofp.oxm.eth_type(eth_type))
1559 match.oxm_list.append(ofp.oxm.ipv4_src(ip_src))
1560 match.oxm_list.append(ofp.oxm.ip_proto(ip_proto))
1561 match.oxm_list.append(ofp.oxm.tcp_src(tcp_src))
1562
1563 request = ofp.message.flow_add(
1564 table_id=29,
1565 cookie=42,
1566 match=match,
1567 instructions=[
1568 ofp.instruction.write_actions(
1569 actions=[ofp.action.set_field(ofp.oxm.ipv4_src(set_ip_src)),
1570 ofp.action.set_field(ofp.oxm.tcp_src(set_tcp_src))]),
1571 ofp.instruction.goto_table(30)
1572 ],
1573 buffer_id=ofp.OFP_NO_BUFFER,
1574 priority=1)
1575 logging.info("Inserting DNAT flow eth_type %lx, sip %lx, ip_proto %ld, tcp_src %ld, SetFeild: sip %lx, tcp_src %ld",eth_type, ip_src, ip_proto, tcp_src, set_ip_src, set_tcp_src)
1576 ctrl.message_send(request)
1577 return request
1578
1579def get_vtap_lport_config_xml(dp_id, lport, phy_port, vlan, vnid, operation='merge'):
1580 """
1581 Command Example:
1582 of-agent vtap 10001 ethernet 1/1 vid 1
1583 of-agent vtp 10001 vni 10
1584 """
1585 if vlan != 0:
1586 config_vtap_xml="""
1587 <config>
1588 <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
1589 <id>capable-switch-1</id>
1590 <resources>
1591 <port xc:operation="OPERATION">
1592 <resource-id >LPORT</resource-id>
1593 <features>
1594 <current>
1595 <rate>10Gb</rate>
1596 <medium>fiber</medium>
1597 <pause>symmetric</pause>
1598 </current>
1599 <advertised>
1600 <rate>10Gb</rate>
1601 <rate>100Gb</rate>
1602 <medium>fiber</medium>
1603 <pause>symmetric</pause>
1604 </advertised>
1605 <supported>
1606 <rate>10Gb</rate>
1607 <rate>100Gb</rate>
1608 <medium>fiber</medium>
1609 <pause>symmetric</pause>
1610 </supported>
1611 <advertised-peer>
1612 <rate>10Gb</rate>
1613 <rate>100Gb</rate>
1614 <medium>fiber</medium>
1615 <pause>symmetric</pause>
1616 </advertised-peer>
1617 </features>
1618 <ofdpa10:vtap xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
1619 <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
1620 <ofdpa10:vid>VLAN_ID</ofdpa10:vid>
1621 <ofdpa10:vni>VNID</ofdpa10:vni>
1622 </ofdpa10:vtap>
1623 </port>
1624 </resources>
1625 <logical-switches>
1626 <switch>
1627 <id>DATAPATH_ID</id>
1628 <datapath-id>DATAPATH_ID</datapath-id>
1629 <resources>
1630 <port xc:operation="OPERATION">LPORT</port>
1631 </resources>
1632 </switch>
1633 </logical-switches>
1634 </capable-switch>
1635 </config>
1636 """
1637 else:
1638 config_vtap_xml="""
1639 <config>
1640 <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
1641 <id>capable-switch-1</id>
1642 <resources>
1643 <port xc:operation="OPERATION">
1644 <resource-id >LPORT</resource-id>
1645 <features>
1646 <current>
1647 <rate>10Gb</rate>
1648 <medium>fiber</medium>
1649 <pause>symmetric</pause>
1650 </current>
1651 <advertised>
1652 <rate>10Gb</rate>
1653 <rate>100Gb</rate>
1654 <medium>fiber</medium>
1655 <pause>symmetric</pause>
1656 </advertised>
1657 <supported>
1658 <rate>10Gb</rate>
1659 <rate>100Gb</rate>
1660 <medium>fiber</medium>
1661 <pause>symmetric</pause>
1662 </supported>
1663 <advertised-peer>
1664 <rate>10Gb</rate>
1665 <rate>100Gb</rate>
1666 <medium>fiber</medium>
1667 <pause>symmetric</pause>
1668 </advertised-peer>
1669 </features>
1670 <ofdpa10:vtap xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
1671 <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
1672 <ofdpa10:vni>VNID</ofdpa10:vni>
1673 </ofdpa10:vtap>
1674 </port>
1675 </resources>
1676 <logical-switches>
1677 <switch>
1678 <id>DATAPATH_ID</id>
1679 <datapath-id>DATAPATH_ID</datapath-id>
1680 <resources>
1681 <port xc:operation="OPERATION">LPORT</port>
1682 </resources>
1683 </switch>
1684 </logical-switches>
1685 </capable-switch>
1686 </config>
1687 """
1688 str_datapath_id_f= "{:016x}".format(dp_id)
1689 str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
1690 config_vtap_xml=config_vtap_xml.replace("DATAPATH_ID", str_datapath_id)
1691 config_vtap_xml=config_vtap_xml.replace("LPORT", str(int(lport)))
1692 config_vtap_xml=config_vtap_xml.replace("PHY_PORT", str(phy_port))
1693 config_vtap_xml=config_vtap_xml.replace("VLAN_ID", str(vlan))
1694 config_vtap_xml=config_vtap_xml.replace("VNID", str(vnid))
1695 config_vtap_xml=config_vtap_xml.replace("OPERATION", str(operation))
1696 return config_vtap_xml
1697
1698def get_vtep_lport_config_xml(dp_id, lport, src_ip, dst_ip, next_hop_id, vnid, udp_src_port=6633, ttl=25, operation='merge'):
1699 """
1700 Command Example:
1701 of-agent vtep 10002 source user-input-src-ip destination user-input-dst-ip udp-source-port 6633 nexthop 2 ttl 25
1702 of-agent vtp 10001 vni 10
1703 """
1704
1705 config_vtep_xml="""
1706 <config>
1707 <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
1708 <id>capable-switch-1</id>
1709 <resources>
1710 <port xc:operation="OPERATION">
1711 <resource-id>LPORT</resource-id>
1712 <features>
1713 <current>
1714 <rate>10Gb</rate>
1715 <medium>fiber</medium>
1716 <pause>symmetric</pause>
1717 </current>
1718 <advertised>
1719 <rate>10Gb</rate>
1720 <rate>100Gb</rate>
1721 <medium>fiber</medium>
1722 <pause>symmetric</pause>
1723 </advertised>
1724 <supported>
1725 <rate>10Gb</rate>
1726 <rate>100Gb</rate>
1727 <medium>fiber</medium>
1728 <pause>symmetric</pause>
1729 </supported>
1730 <advertised-peer>
1731 <rate>10Gb</rate>
1732 <rate>100Gb</rate>
1733 <medium>fiber</medium>
1734 <pause>symmetric</pause>
1735 </advertised-peer>
1736 </features>
1737 <ofdpa10:vtep xmlns:ofdpa10="urn:bcm:ofdpa10:accton01">
1738 <ofdpa10:src-ip>SRC_IP</ofdpa10:src-ip>
1739 <ofdpa10:dest-ip>DST_IP</ofdpa10:dest-ip>
1740 <ofdpa10:udp-src-port>UDP_SRC_PORT</ofdpa10:udp-src-port>
1741 <ofdpa10:vni xc:operation="OPERATION">
1742 <ofdpa10:id>VNID</ofdpa10:id>
1743 </ofdpa10:vni>
1744 <ofdpa10:nexthop-id>NEXT_HOP_ID</ofdpa10:nexthop-id>
1745 <ofdpa10:ttl>TTL</ofdpa10:ttl>
1746 </ofdpa10:vtep>
1747 </port>
1748 </resources>
1749 <logical-switches>
1750 <switch>
1751 <id>DATAPATH_ID</id>
1752 <datapath-id>DATAPATH_ID</datapath-id>
1753 <resources>
1754 <port xc:operation="OPERATION">LPORT</port>
1755 </resources>
1756 </switch>
1757 </logical-switches>
1758 </capable-switch>
1759 </config>
1760 """
1761 str_datapath_id_f= "{:016x}".format(dp_id)
1762 str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
1763 config_vtep_xml=config_vtep_xml.replace("DATAPATH_ID", str_datapath_id)
1764 config_vtep_xml=config_vtep_xml.replace("LPORT", str(int(lport)))
1765 config_vtep_xml=config_vtep_xml.replace("SRC_IP", str(src_ip))
1766 config_vtep_xml=config_vtep_xml.replace("DST_IP", str(dst_ip))
1767 config_vtep_xml=config_vtep_xml.replace("UDP_SRC_PORT", str(udp_src_port))
1768 config_vtep_xml=config_vtep_xml.replace("NEXT_HOP_ID", str(next_hop_id))
1769 config_vtep_xml=config_vtep_xml.replace("TTL", str(ttl))
1770 config_vtep_xml=config_vtep_xml.replace("VNID", str(vnid))
1771 config_vtep_xml=config_vtep_xml.replace("OPERATION", str(operation))
1772
1773 return config_vtep_xml
1774
1775def get_next_hop_config_xml(next_hop_id, dst_mac, phy_port, vlan, operation='merge'):
1776 #of-agent nexthop 2 destination user-input-dst-mac ethernet 1/2 vid 2
1777 config_nexthop_xml="""
1778 <config>
1779 <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
1780 <ofdpa10:next-hop xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
1781 <ofdpa10:id>NEXT_HOP_ID</ofdpa10:id>
1782 <ofdpa10:dest-mac>DST_MAC</ofdpa10:dest-mac>
1783 <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
1784 <ofdpa10:vid>VLAN_ID</ofdpa10:vid>
1785 </ofdpa10:next-hop>
1786 </of11-config:capable-switch>
1787 </config>
1788 """
1789 config_nexthop_xml=config_nexthop_xml.replace("VLAN_ID", str(vlan))
1790 config_nexthop_xml=config_nexthop_xml.replace("PHY_PORT", str(phy_port))
1791 config_nexthop_xml=config_nexthop_xml.replace("NEXT_HOP_ID", str(next_hop_id))
1792 config_nexthop_xml=config_nexthop_xml.replace("DST_MAC", str(dst_mac))
1793 config_nexthop_xml=config_nexthop_xml.replace("OPERATION", str(operation))
1794 return config_nexthop_xml
1795
1796def get_vni_config_xml(vni_id, mcast_ipv4, next_hop_id, operation='merge'):
1797 #of-agent vni 10 multicast 224.1.1.1 nexthop 20
1798 if mcast_ipv4!=None:
1799 config_vni_xml="""
1800 <config>
1801 <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
1802 <ofdpa10:vni xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
1803 <ofdpa10:id>VNID</ofdpa10:id>
1804 <ofdpa10:vni-multicast-group>MCAST_IP</ofdpa10:vni-multicast-group>
1805 <ofdpa10:multicast-group-nexthop-id>NEXT_HOP_ID</ofdpa10:multicast-group-nexthop-id>
1806 </ofdpa10:vni>
1807 </of11-config:capable-switch>
1808 </config>
1809 """
1810 config_vni_xml=config_vni_xml.replace("NEXT_HOP_ID", str(next_hop_id))
1811 config_vni_xml=config_vni_xml.replace("MCAST_IP", str(mcast_ipv4))
1812 else:
1813 config_vni_xml="""
1814 <config>
1815 <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
1816 <ofdpa10:vni xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
1817 <ofdpa10:id>VNID</ofdpa10:id>
1818 </ofdpa10:vni>
1819 </of11-config:capable-switch>
1820 </config>
1821 """
1822
1823 config_vni_xml=config_vni_xml.replace("VNID", str(vni_id))
1824 config_vni_xml=config_vni_xml.replace("OPERATION", str(operation))
1825 return config_vni_xml
1826
1827def get_featureReplay(self):
1828 req = ofp.message.features_request()
1829 res, raw = self.controller.transact(req)
1830 self.assertIsNotNone(res, "Did not receive a response from the DUT.")
1831 self.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
1832 ("Unexpected packet type %d received in response to "
1833 "OFPT_FEATURES_REQUEST") % res.type)
1834 return res
1835
1836def send_edit_config(switch_ip, xml, target='runing'):
1837 NETCONF_ACCOUNT="netconfuser"
1838 NETCONF_PASSWD="netconfuser"
1839 with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
1840 try:
1841 m.edit_config(target='running',
1842 config=xml,
1843 default_operation='merge',
1844 error_option='stop-on-error')
1845
1846 except Exception as e:
1847 logging.info("Fail to set xml %s", xml)
1848 return False
1849
1850 #return m.get_config(source='running').data_xml
1851 return True
1852
1853def send_delete_config(switch_ip, xml, target='runing'):
1854 NETCONF_ACCOUNT="netconfuser"
1855 NETCONF_PASSWD="netconfuser"
1856 with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
1857 try:
1858 m.edit_config(target='running',
1859 config=xml,
1860 default_operation='delete',
1861 error_option='stop-on-error')
1862
1863 except Exception as e:
1864 logging.info("Fail to set xml %s", xml)
1865 return False
1866
1867 #return m.get_config(source='running').data_xml
1868 return True
1869
1870def get_edit_config(switch_ip, target='runing'):
1871 NETCONF_ACCOUNT="netconfuser"
1872 NETCONF_PASSWD="netconfuser"
1873 with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
1874 return m.get_config(source='running').data_xml
1875
1876
1877"""
1878MPLS
1879"""
1880
1881OFDPA_MPLS_SUBTYPE_SHIFT=24
1882OFDPA_MPLS_GROUP_SUBTYPE_L2_VPN_LABEL=1
1883OFDPA_MPLS_GROUP_SUBTYPE_L3_VPN_LABEL=2
1884OFDPA_MPLS_GROUP_SUBTYPE_TUNNEL_LABEL1=3
1885OFDPA_MPLS_GROUP_SUBTYPE_TUNNEL_LABEL2=4
1886OFDPA_MPLS_GROUP_SUBTYPE_SWAP_LABEL=5
1887OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP=6
1888OFDPA_MPLS_GROUP_SUBTYPE_ECMP=8
1889OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG=10
1890
1891
1892
1893
1894def encode_mpls_interface_group_id(subtype, index):
1895 index=index&0x00ffffff
1896 assert(subtype==0)
1897 return index + (9 << OFDPA_GROUP_TYPE_SHIFT)+(subtype<<OFDPA_MPLS_SUBTYPE_SHIFT)
1898
1899def encode_mpls_label_group_id(subtype, index):
1900 index=index&0x00ffffff
1901 assert(subtype <=5 or subtype==0)
1902 #1: l2 vpn label
1903 #2: l3 vpn label
1904 #3: mpls tunnel label 1
1905 #4: mpls tunnel lable 2
1906 #5: mpls swap label
1907 return index + (9 << OFDPA_GROUP_TYPE_SHIFT)+(subtype<<OFDPA_MPLS_SUBTYPE_SHIFT)
1908
1909def encode_mpls_forwarding_group_id(subtype, index):
1910 index=index&0x00ffffff
1911 assert(subtype==6 or subtype==8 or subtype==10)
1912 return index + (10 << OFDPA_GROUP_TYPE_SHIFT)+(subtype<<OFDPA_MPLS_SUBTYPE_SHIFT)
1913
1914
1915def add_mpls_intf_group(ctrl, ref_gid, dst_mac, src_mac, vid, index, subtype=0, send_barrier=False, add=True):
1916 action=[]
1917 action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
1918 action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
1919 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vid)))
1920 action.append(ofp.action.group(ref_gid))
1921
1922 buckets = [ofp.bucket(actions=action)]
1923
1924 mpls_group_id =encode_mpls_interface_group_id(subtype, index)
1925 if add:
1926 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
1927 group_id=mpls_group_id,
1928 buckets=buckets
1929 )
1930 else:
1931 request = ofp.message.group_modify(group_type=ofp.OFPGT_INDIRECT,
1932 group_id=mpls_group_id,
1933 buckets=buckets
1934 )
1935
1936
1937 logging.debug("Adding MPLS interface group %02x, src_mac %s , dst_mac %s , vid %d", mpls_group_id, src_mac, dst_mac, vid)
1938 ctrl.message_send(request)
1939
1940 if send_barrier:
1941 do_barrier(ctrl)
1942 return mpls_group_id, request
1943
1944def add_mpls_tunnel_label_group(
1945 ctrl,
1946 ref_gid,
1947 subtype,
1948 index,
1949 label,
1950 ):
1951
1952 action=[]
1953 action.append(ofp.action.push_mpls(0x8847))
1954 action.append(ofp.action.set_field(ofp.oxm.mpls_label(label)))
1955 action.append(ofp.action.group(ref_gid))
1956 buckets = [ofp.bucket(actions=action)]
1957
1958 mpls_group_id = encode_mpls_label_group_id(subtype, index)
1959 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
1960 group_id=mpls_group_id,
1961 buckets=buckets
1962 )
1963 ctrl.message_send(request)
1964
1965 return mpls_group_id, request
1966
1967def add_mpls_swap_label_group(
1968 ctrl,
1969 ref_gid,
1970 subtype,
1971 index,
1972 label,
1973 ):
1974
1975 action=[]
1976 action.append(ofp.action.set_field(ofp.oxm.mpls_label(label)))
1977 action.append(ofp.action.group(ref_gid))
1978 buckets = [ofp.bucket(actions=action)]
1979
1980 mpls_group_id = encode_mpls_label_group_id(subtype, index)
1981 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
1982 group_id=mpls_group_id,
1983 buckets=buckets
1984 )
1985 logging.debug("Adding MPLS Swap group %02x, label %d", mpls_group_id, label)
1986 ctrl.message_send(request)
1987
1988 return mpls_group_id, request
1989
1990def add_mpls_label_group(ctrl, subtype, index, ref_gid,
1991 lmep_id=-1,
1992 qos_index=-1,
1993 push_l2_header=False,
1994 push_vlan=False,
1995 push_mpls_header=False,
1996 push_cw=False,
1997 set_mpls_label=None,
1998 set_bos=None,
1999 set_tc=None,
2000 set_tc_from_table=False,
2001 cpy_tc_outward=False,
2002 set_ttl=None,
2003 cpy_ttl_outward=False,
2004 oam_lm_tx_count=False,
2005 set_pri_from_table=False,
2006 send_barrier=False
2007 ):
2008 """
2009 @ref_gid: only can be mpls intf group or mpls tunnel label 1/2 group
2010 """
2011 action=[]
2012
2013 if push_vlan== True:
2014 action.append(ofp.action.push_vlan(0x8100))
2015 if push_mpls_header== True:
2016 action.append(ofp.action.push_mpls(0x8847))
2017 if set_mpls_label != None:
2018 action.append(ofp.action.set_field(ofp.oxm.mpls_label(set_mpls_label)))
2019 if set_bos != None:
2020 action.append(ofp.action.set_field(ofp.oxm.mpls_bos(set_bos)))
2021 if set_tc != None:
2022 assert(set_tc_from_table==False)
2023 action.append(ofp.action.set_field(ofp.oxm.mpls_tc(set_tc)))
2024 if set_ttl != None:
2025 action.append(ofp.action.set_mpls_ttl(set_ttl))
2026 if cpy_ttl_outward == True:
2027 action.append(ofp.action.copy_ttl_out())
2028 """
2029 ofdpa experimenter
2030 """
2031 if push_l2_header== True:
2032 action.append(ofp.action.ofdpa_push_l2_header())
2033 if set_tc_from_table== True:
2034 assert(qos_index>=0)
2035 assert(set_tc == None)
2036 action.append(ofp.action.ofdpa_set_tc_from_table(qos_index))
2037 if cpy_tc_outward == True:
2038 action.append(ofp.action.ofdpa_copy_tc_out())
2039 if oam_lm_tx_count == True:
2040 assert(qos_index>=0 and lmep_id>=0)
2041 action.append(ofp.action.ofdpa_oam_lm_tx_count(lmep_id, qos_index))
2042 if set_pri_from_table == True:
2043 assert(qos_index>=0)
2044 action.append(ofp.action.ofdpa_set_qos_from_table(qos_index))
2045 if push_cw == True:
2046 action.append(ofp.action.ofdpa_push_cw())
2047
2048 action.append(ofp.action.group(ref_gid))
2049 buckets = [ofp.bucket(actions=action)]
2050
2051 mpls_group_id = encode_mpls_label_group_id(subtype, index)
2052 request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
2053 group_id=mpls_group_id,
2054 buckets=buckets
2055 )
2056 ctrl.message_send(request)
2057
2058 if send_barrier:
2059 do_barrier(ctrl)
2060
2061 return mpls_group_id, request
2062
2063def add_mpls_l2_port_flow(ctrl, of_port, mpls_l2_port, tunnel_index, ref_gid, qos_index=0, goto=MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE):
2064 """
2065 Only action is Group, which must indicate one of:
2066 MPLS L2 VPN Label or Fast Failover Protection Group.
2067 ref_gid contains this information
2068 """
2069
2070 match = ofp.match()
2071
2072 write_actions = []
2073 write_actions.append(ofp.action.group(ref_gid))
2074 apply_actions = []
2075
2076 if goto==MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE:
2077 tunnel_id = tunnel_index + ofp.oxm.TUNNEL_ID_BASE
2078 match.oxm_list.append(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port))
2079 match.oxm_list.append(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE))
2080 assert(qos_index>=0)
2081 apply_actions.append(ofp.action.set_field(ofp.oxm.exp1ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_QOS_INDEX, value=qos_index)))
2082
2083 request = ofp.message.flow_add(
2084 table_id=MPLS_L2_PORT_FLOW_TABLE,
2085 cookie=42,
2086 match=match,
2087 instructions=[
2088 ofp.instruction.apply_actions(actions=apply_actions),
2089 ofp.instruction.write_actions(actions=write_actions),
2090 ofp.instruction.goto_table(goto)
2091 ],
2092 buffer_id=ofp.OFP_NO_BUFFER,
2093 priority=1)
2094 logging.info("Inserting flow for Pseudowire Initiation %d mpls_l2_port, %d tunnel_id, action %x group and go to table %d", mpls_l2_port, tunnel_id, ref_gid, MPLS_L2_PORT_DSCP_TRUST_FLOW_TABLE)
2095 ctrl.message_send(request)
2096
2097 if goto==ACL_FLOW_TABLE:
2098 tunnel_id = tunnel_index + ofp.oxm.TUNNEL_ID_BASE
2099 match.oxm_list.append(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port))
2100 match.oxm_list.append(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE_CROSS_CONNECT))
2101 request = ofp.message.flow_add(
2102 table_id=MPLS_L2_PORT_FLOW_TABLE,
2103 cookie=42,
2104 match=match,
2105 instructions=[
2106 ofp.instruction.apply_actions(actions=apply_actions),
2107 ofp.instruction.write_actions(actions=write_actions),
2108 ofp.instruction.goto_table(goto)
2109 ],
2110 buffer_id=ofp.OFP_NO_BUFFER,
2111 priority=1)
2112 logging.info("Inserting flow for VLAN Cross Connect %d mpls_l2_port, %d tunnel_id, action %x group and go to table %d", mpls_l2_port, tunnel_id, ref_gid, ACL_FLOW_TABLE)
2113 ctrl.message_send(request)
2114
2115 return request
2116
2117def add_mpls_forwarding_group(ctrl, subtype, index, ref_gids,
2118 watch_port=None,
2119 watch_group=ofp.OFPP_ANY,
2120 push_vlan=None,
2121 pop_vlan=None,
2122 set_vid=None):
2123 assert(subtype == OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP
2124 or subtype == OFDPA_MPLS_GROUP_SUBTYPE_ECMP
2125 or subtype == OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG)
2126
2127 buckets=[]
2128 if subtype == OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP:
2129 group_type = ofp.OFPGT_FF
2130 for gid in ref_gids:
2131 action=[]
2132 action.append(ofp.action.group(gid))
2133 buckets.append(ofp.bucket(watch_port=watch_port, watch_group=watch_group,actions=action))
2134
2135 elif subtype == OFDPA_MPLS_GROUP_SUBTYPE_ECMP:
2136 group_type = ofp.OFPGT_SELECT
2137 for gid in ref_gids:
2138 action=[]
2139 action.append(ofp.action.group(gid))
2140 buckets.append(ofp.bucket(actions=action))
2141
2142 elif subtype == OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG:
2143 group_type = ofp.OFPGT_INDIRECT
2144 action=[]
2145 if set_vid!=None:
2146 action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+set_vid)))
2147 if push_vlan!=None:
2148 action.append(ofp.action.push_vlan(push_vlan))
2149 if pop_vlan!=None:
2150 action.append(ofp.action.pop_vlan())
2151 action.append(ofp.action.group(ref_gids[0]))
2152 buckets.append(ofp.bucket(actions=action))
2153
2154 mpls_group_id = encode_mpls_forwarding_group_id(subtype, index)
2155 request = ofp.message.group_add(group_type=group_type,
2156 group_id=mpls_group_id,
2157 buckets=buckets
2158 )
2159 ctrl.message_send(request)
2160 return mpls_group_id, request
2161
2162def add_one_egress_vlan_tpid_table_flow(ctrl, of_port):
2163 # Used for changing ethertype of outer vlan header to 0x88a8
2164
2165 match = ofp.match()
2166 match.oxm_list.append(ofp.oxm.exp4ByteValue(ofp.oxm.OFDPA_EXP_TYPE_ACTSET_OUTPUT, of_port, ONF_EXPERIMENTER_ID))
2167 match.oxm_list.append(ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT))
2168
2169 actions = []
2170 actions.append(ofp.action.copy_field(
2171 12, 0, 0, ['\x80\x00\x0c\x02', ofp.oxm.exp4ByteReg(oxm_field = 1).pack()])) # VLAN_VID, PACKET_REG(1)
2172 actions.append(ofp.action.pop_vlan())
2173 actions.append(ofp.action.push_vlan(0x88a8))
2174 actions.append(ofp.action.copy_field(
2175 12, 0, 0, [ofp.oxm.exp4ByteReg(oxm_field = 1).pack(), '\x80\x00\x0c\x02'])) # PACKET_REG(1), VLAN_VID
2176
2177 request = ofp.message.flow_add(
2178 table_id=EGRESS_TPID_FLOW_TABLE,
2179 cookie=42,
2180 match=match,
2181 instructions=[
2182 ofp.instruction.apply_actions(
2183 actions=actions
2184 ),
2185 ],
2186 priority=0)
2187
2188 ctrl.message_send(request)
2189
2190 return
2191
2192"""
2193display
2194"""
2195def print_current_table_flow_stat(ctrl, table_id=0xff):
2196 stat_req=ofp.message.flow_stats_request()
2197 response, pkt = ctrl.transact(stat_req)
2198 if response == None:
2199 print "no response"
2200 return None
2201 print len(response.entries)
2202 for obj in response.entries:
2203 print "match ", obj.match
2204 print "cookie", obj.cookie
2205 print "priority", obj.priority
2206 print "idle_timeout", obj.idle_timeout
2207 print "hard_timeout", obj.hard_timeout
2208 #obj.actions
2209 print "packet count: %lx"%obj.packet_count
2210