Initial set of Fabric switch test cases
Change-Id: I86fd2b67d3b773aa496f5ef61f1e1fdf51fd9925
diff --git a/Fabric/Utilities/accton/accton_util.py b/Fabric/Utilities/accton/accton_util.py
new file mode 100755
index 0000000..0f32e76
--- /dev/null
+++ b/Fabric/Utilities/accton/accton_util.py
@@ -0,0 +1,2210 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+import time
+from oftest.testutils import *
+from oftest.parse import parse_ipv6
+
+from ncclient import manager
+import ncclient
+
+OFDPA_GROUP_TYPE_SHIFT=28
+OFDPA_VLAN_ID_SHIFT =16
+OFDPA_TUNNEL_ID_SHIFT =12
+OFDPA_TUNNEL_SUBTYPE_SHIFT=10
+
+#VLAN_TABLE_FLAGS
+VLAN_TABLE_FLAG_ONLY_UNTAG=1
+VLAN_TABLE_FLAG_ONLY_TAG =2
+VLAN_TABLE_FLAG_ONLY_BOTH =3
+VLAN_TABLE_FLAG_ONLY_STACKED=5
+VLAN_TABLE_FLAG_PRIORITY=6
+VLAN_TABLE_FLAG_ONLY_UNTAG_PRIORITY=7
+VLAN_TABLE_FLAG_ONLY_POP_VLAN=8
+
+PORT_FLOW_TABLE=0
+VLAN_FLOW_TABLE=10
+VLAN_1_FLOW_TABLE=11
+MPLS_L2_PORT_FLOW_TABLE=13
+MPLS_L2_PORT_DSCP_TRUST_FLOW_TABLE=15
+MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE=16
+TERMINATION_FLOW_TABLE=20
+MPLS_TYPE_FLOW_TABLE=29
+UCAST_ROUTING_FLOW_TABLE=30
+MCAST_ROUTING_FLOW_TABLE=40
+BRIDGE_FLOW_TABLE=50
+ACL_FLOW_TABLE=60
+EGRESS_TPID_FLOW_TABLE = 235
+
+ONF_EXPERIMENTER_ID = 0x4F4E4600
+
+EGRESS_VLAN_FLOW_TABLE=210
+EGRESS_VLAN_1_FLOW_TABLE=211
+EGRESS_MAINTENANCE_POINT_FLOW_TABLE=226
+EGRESS_DSCP_TABLE=230
+EGRESS_TPID_TABLE=235
+EGRESS_SOURCE_MAC_LEARNING_TABLE=254
+
+def convertIP4toStr(ip_addr):
+ a=(ip_addr&0xff000000)>>24
+ b=(ip_addr&0x00ff0000)>>16
+ c=(ip_addr&0x0000ff00)>>8
+ d=(ip_addr&0x000000ff)
+ return str(a)+"."+str(b)+"."+str(c)+"."+str(d)
+
+def convertMACtoStr(mac):
+ if not isinstance(mac, list):
+ assert(0)
+
+ return ':'.join(['%02X' % x for x in mac])
+
+def getSwitchCpuMACFromDPID(dpid):
+ str_datapath_id_f= "{:016x}".format(dpid)
+ str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
+ switch_cpu_mac_str=str_datapath_id[6:]
+ switch_cpu_mac = switch_cpu_mac_str.split(":")
+ switch_cpu_mac=[int(switch_cpu_mac[i],16) for i in range(0, len(switch_cpu_mac))]
+
+ return switch_cpu_mac_str, switch_cpu_mac
+
+def DumpGroup(stats, verify_group_stats, always_show=True):
+ if(len(stats) > len(verify_group_stats)):
+ min_len = len(verify_group_stats)
+ print "Stats Len is not the same, stats>verify_group_stats"
+ if(len(stats)< len(verify_group_stats)):
+ min_len = len(stats)
+ print "Stats Len is not the same, stats<verify_group_stats"
+ else:
+ min_len = len(stats)
+
+ print "\r\n"
+ for i in range(min_len):
+ gs = stats[i]
+ gv = verify_group_stats[i]
+ print "FromSwtich:(GID=%lx, TYPE=%lx)\r\nVerify :(GID=%lx, TYPE=%lx)"%(gs.group_id, gs.group_type, gv.group_id, gv.group_type)
+ if(len(gs.buckets) != len(gv.buckets)):
+ print "buckets len is not the same gs %lx, gv %lx",(len(gs.buckets), len(gv.buckets))
+
+ for j in range(len(gs.buckets)):
+ b1=gs.buckets[j]
+ b2=gv.buckets[j]
+ if(len(b1.actions) != len(b2.actions)):
+ print "action len is not the same"
+
+ for k in range(len(b1.actions)):
+ a1=b1.actions[k]
+ a2=b2.actions[k]
+ if(always_show == True):
+ print "a1:"+a1.show()
+ print "a2:"+a2.show()
+
+def AssertGroup(self, stats, verify_group_stats):
+ self.assertTrue(len(stats) ==len(verify_group_stats), "stats len is not the same")
+
+ for i in range(len(stats)):
+ gs = stats[i]
+ gv = verify_group_stats[i]
+ self.assertTrue(len(gs.buckets) == len(gv.buckets), "buckets len is not the same")
+
+ for j in range(len(gs.buckets)):
+ b1=gs.buckets[j]
+ b2=gv.buckets[j]
+ self.assertTrue(len(b1.actions) == len(b2.actions), "action len is not the same")
+
+ for k in range(len(b1.actions)):
+ a1=b1.actions[k]
+ a2=b2.actions[k]
+ self.assertEquals(a1, a2, "action is not the same")
+
+def encode_l2_interface_group_id(vlan, id):
+ return id + (vlan << OFDPA_VLAN_ID_SHIFT)
+
+def encode_l2_rewrite_group_id(id):
+ return id + (1 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l3_unicast_group_id(id):
+ return id + (2 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l2_mcast_group_id(vlan, id):
+ return id + (vlan << OFDPA_VLAN_ID_SHIFT) + (3 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l2_flood_group_id(vlan, id):
+ return id + (vlan << OFDPA_VLAN_ID_SHIFT) + (4 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l3_interface_group_id(id):
+ return id + (5 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l3_mcast_group_id(vlan, id):
+ return id + (vlan << OFDPA_VLAN_ID_SHIFT)+(6 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l3_ecmp_group_id(id):
+ return id + (7 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l2_unfiltered_group_id(id):
+ return id + (11 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l2_loadbal_group_id(id):
+ return id + (12 << OFDPA_GROUP_TYPE_SHIFT)
+
+def encode_l2_overlay_group_id(tunnel_id, subtype, index):
+ tunnel_id=tunnel_id&0xffff #16 bits
+ subtype = subtype&3 #2 bits
+ index = index & 0x3f #10 bits
+ return index + (tunnel_id << OFDPA_TUNNEL_ID_SHIFT)+ (subtype<<OFDPA_TUNNEL_SUBTYPE_SHIFT)+(8 << OFDPA_GROUP_TYPE_SHIFT)
+
+def add_l2_unfiltered_group(ctrl, ports, send_barrier=False, allow_vlan_translation=1):
+ # group table
+ # set up untag groups for each port
+ group_id_list=[]
+ msgs=[]
+ for of_port in ports:
+ # do stuff
+ group_id = encode_l2_unfiltered_group_id(of_port)
+ group_id_list.append(group_id)
+ actions = [ofp.action.output(of_port)]
+
+ actions.append(ofp.action.set_field(ofp.oxm.exp1ByteValue(exp_type=24, value=allow_vlan_translation)))
+ buckets = [ofp.bucket(actions=actions)]
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ msgs.append(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return group_id_list, msgs
+
+def add_one_l2_unfiltered_group(ctrl, of_port, send_barrier=False):
+ # group table
+ # set up untag groups for each port
+ group_id = encode_l2_unfiltered_group_id(of_port)
+ actions = [ofp.action.output(of_port)]
+ actions.append(ofp.action.set_field(ofp.oxm.exp1ByteValue(exp_type=24, value=1)))
+
+ buckets = [ofp.bucket(actions=actions)]
+ request = ofp.message.group_add(
+ group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return group_id, request
+
+def add_l2_interface_group(ctrl, ports, vlan_id=1, is_tagged=False, send_barrier=False):
+ # group table
+ # set up untag groups for each port
+ group_id_list=[]
+ msgs=[]
+ for of_port in ports:
+ # do stuff
+ group_id = encode_l2_interface_group_id(vlan_id, of_port)
+ group_id_list.append(group_id)
+ if is_tagged:
+ actions = [
+ ofp.action.output(of_port),
+ ]
+ else:
+ actions = [
+ ofp.action.pop_vlan(),
+ ofp.action.output(of_port),
+ ]
+
+ buckets = [
+ ofp.bucket(actions=actions),
+ ]
+
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ msgs.append(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return group_id_list, msgs
+
+def add_one_l2_interface_group(ctrl, port, vlan_id=1, is_tagged=False, send_barrier=False):
+ # group table
+ # set up untag groups for each port
+ group_id = encode_l2_interface_group_id(vlan_id, port)
+
+ if is_tagged:
+ actions = [
+ ofp.action.output(port),
+ ]
+ else:
+ actions = [
+ ofp.action.pop_vlan(),
+ ofp.action.output(port),
+ ]
+
+ buckets = [
+ ofp.bucket(actions=actions),
+ ]
+
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return group_id, request
+
+def add_l2_mcast_group(ctrl, ports, vlanid, mcast_grp_index):
+ buckets=[]
+ for of_port in ports:
+ group_id = encode_l2_interface_group_id(vlanid, of_port)
+ action=[ofp.action.group(group_id)]
+ buckets.append(ofp.bucket(actions=action))
+
+ group_id =encode_l2_mcast_group_id(vlanid, mcast_grp_index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l2_flood_group(ctrl, ports, vlanid, id):
+ buckets=[]
+ for of_port in ports:
+ group_id = encode_l2_interface_group_id(vlanid, of_port)
+ action=[ofp.action.group(group_id)]
+ buckets.append(ofp.bucket(actions=action))
+
+ group_id =encode_l2_flood_group_id(vlanid, id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l2_flood_group_with_gids(ctrl, gids, vlanid, id, send_barrier=False):
+ buckets=[]
+ for gid in gids:
+ action=[ofp.action.group(gid)]
+ buckets.append(ofp.bucket(actions=action))
+
+ group_id =encode_l2_flood_group_id(vlanid, id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def mod_l2_flood_group(ctrl, ports, vlanid, id):
+ buckets=[]
+ for of_port in ports:
+ group_id = encode_l2_interface_group_id(vlanid, of_port)
+ action=[ofp.action.group(group_id)]
+ buckets.append(ofp.bucket(actions=action))
+
+ group_id =encode_l2_flood_group_id(vlanid, id)
+ request = ofp.message.group_modify(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+
+def add_l2_rewrite_group(ctrl, port, vlanid, id, src_mac, dst_mac):
+ group_id = encode_l2_interface_group_id(vlanid, port)
+
+ action=[]
+ if src_mac is not None:
+ action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
+
+ if dst_mac is not None:
+ action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
+
+ action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlanid)))
+
+ action.append(ofp.action.group(group_id))
+
+ buckets = [ofp.bucket(actions=action)]
+
+ group_id =encode_l2_rewrite_group_id(id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l3_unicast_group(ctrl, port, vlanid, id, src_mac, dst_mac, send_barrier=False, gid=None):
+
+ if (not gid):
+ group_id = encode_l2_interface_group_id(vlanid, port)
+ else:
+ group_id = gid
+
+ action=[]
+ if src_mac is not None:
+ action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
+
+ if dst_mac is not None:
+ action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
+
+ action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlanid)))
+
+ action.append(ofp.action.group(group_id))
+
+ buckets = [ofp.bucket(actions=action)]
+
+ group_id =encode_l3_unicast_group_id(id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_l3_interface_group(ctrl, port, vlanid, id, src_mac):
+ group_id = encode_l2_interface_group_id(vlanid, port)
+
+ action=[]
+ action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
+ action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlanid)))
+ action.append(ofp.action.group(group_id))
+
+ buckets = [ofp.bucket(actions=action)]
+
+ group_id =encode_l3_interface_group_id(id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+
+def add_l2_loadbal_group(ctrl, id, l2_unfil_intf_groups, send_barrier=False):
+ buckets=[]
+ for group in l2_unfil_intf_groups:
+ buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
+
+ group_id=encode_l2_loadbal_group_id(id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_SELECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return group_id, request
+
+def mod_l2_loadbal_group(ctrl, id, l2_unfil_intf_groups, send_barrier=False):
+ buckets=[]
+ for group in l2_unfil_intf_groups:
+ buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
+
+ group_id =encode_l2_loadbal_group_id(id)
+ request = ofp.message.group_modify(group_type=ofp.OFPGT_SELECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+
+def add_l3_ecmp_group(ctrl, id, l3_ucast_groups, send_barrier=False):
+ buckets=[]
+ for group in l3_ucast_groups:
+ buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
+
+ group_id =encode_l3_ecmp_group_id(id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_SELECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def mod_l3_ecmp_group(ctrl, id, l3_ucast_groups):
+ buckets=[]
+ for group in l3_ucast_groups:
+ buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
+
+ group_id =encode_l3_ecmp_group_id(id)
+ request = ofp.message.group_modify(group_type=ofp.OFPGT_SELECT,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l3_mcast_group(ctrl, vid, mcast_group_id, groups_on_buckets):
+ buckets=[]
+ for group in groups_on_buckets:
+ buckets.append(ofp.bucket(actions=[ofp.action.group(group)]))
+
+ group_id =encode_l3_mcast_group_id(vid, mcast_group_id)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l2_overlay_flood_over_unicast_tunnel_group(ctrl, tunnel_id, ports, index):
+ buckets=[]
+ for port in ports:
+ buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
+
+ group_id=encode_l2_overlay_group_id(tunnel_id, 0, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l2_overlay_flood_over_mcast_tunnel_group(ctrl, tunnel_id, ports, index):
+ buckets=[]
+ for port in ports:
+ buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
+
+ group_id=encode_l2_overlay_group_id(tunnel_id, 1, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l2_overlay_mcast_over_unicast_tunnel_group(ctrl, tunnel_id, ports, index):
+ buckets=[]
+ for port in ports:
+ buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
+
+ group_id=encode_l2_overlay_group_id(tunnel_id, 2, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_l2_overlay_mcast_over_mcast_tunnel_group(ctrl, tunnel_id, ports, index):
+ buckets=[]
+ for port in ports:
+ buckets.append(ofp.bucket(actions=[ofp.action.output(port)]))
+
+ group_id=encode_l2_overlay_group_id(tunnel_id, 3, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_ALL,
+ group_id=group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return request
+
+def add_port_table_flow(ctrl, is_overlay=True):
+ match = ofp.match()
+
+ if is_overlay == True:
+ match.oxm_list.append(ofp.oxm.in_port(0x10000))
+ NEXT_TABLE=50
+ else:
+ match.oxm_list.append(ofp.oxm.in_port(0))
+ NEXT_TABLE=10
+
+ request = ofp.message.flow_add(
+ table_id=0,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.goto_table(NEXT_TABLE)
+ ],
+ priority=0)
+ logging.info("Add port table, match port %lx" % 0x10000)
+ ctrl.message_send(request)
+
+def pop_vlan_flow(ctrl, ports, vlan_id=1):
+ # table 10: vlan
+ # goto to table 20
+ msgs=[]
+ for of_port in ports:
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.pop_vlan()
+ ]
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
+ ctrl.message_send(request)
+
+
+ return msgs
+
+def add_vlan_table_flow(ctrl, ports, vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
+ # table 10: vlan
+ # goto to table 20
+ msgs=[]
+ for of_port in ports:
+ if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH) or (flag == 4):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.pop_vlan()
+ ]
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
+ ctrl.message_send(request)
+
+ if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0, 0x1fff))
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id))
+ ]
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
+ ctrl.message_send(request)
+ msgs.append(request)
+
+ if (flag == 4) :
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000, 0x1fff))
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id))
+ ]
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
+ ctrl.message_send(request)
+ msgs.append(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return msgs
+
+def del_vlan_table_flow(ctrl, ports, vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False):
+ # table 10: vlan
+ # goto to table 20
+ msgs=[]
+ for of_port in ports:
+ if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
+ request = ofp.message.flow_delete(
+ table_id=10,
+ cookie=42,
+ match=match,
+ priority=0)
+ logging.info("Del vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
+ ctrl.message_send(request)
+
+ if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0, 0xfff))
+ request = ofp.message.flow_delete(
+ table_id=10,
+ cookie=42,
+ match=match,
+ priority=0)
+ logging.info("Del vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
+ ctrl.message_send(request)
+ msgs.append(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return msgs
+
+def add_vlan_table_flow_pvid(ctrl, in_port, match_vid=None, pvid=1, send_barrier=False):
+ """it will tag pack as untagged packet wether it has tagg or not"""
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(in_port))
+ actions=[]
+ if match_vid == None:
+ match.oxm_list.append(ofp.oxm.vlan_vid(0))
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+pvid)))
+ goto_table=20
+ else:
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+match_vid, 0x1fff))
+ actions.append(ofp.action.push_vlan(0x8100))
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+pvid)))
+ goto_table=20
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=actions)
+ ,ofp.instruction.goto_table(goto_table)
+ ],
+ priority=0)
+ logging.info("Add PVID %d on port %d and go to table %ld" %( pvid, in_port, goto_table))
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+def add_vlan_table_flow_allow_all_vlan(ctrl, in_port, send_barrier=False):
+ """it st flow allow all vlan tag on this port"""
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(in_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000, 0x1000))
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add allow all vlan on port %d " %(in_port))
+ ctrl.message_send(request)
+
+def 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):
+ # Install a flow for VLAN translation
+ # in VLAN table.
+ # table 10: vlan
+ # goto to table 20
+ if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH) or (flag == 4):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id,0x1fff))
+
+ actions=[]
+ if vrf!=0:
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
+ if new_vlan_id != -1:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_vlan_id)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
+ ctrl.message_send(request)
+
+
+def add_one_egress_vlan_table_flow(ctrl, of_port, match_vlan, inner_vlan, outer_vlan):
+
+ # used for translating single to double tagged packets only
+
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.exp4ByteValue(ofp.oxm.OFDPA_EXP_TYPE_ACTSET_OUTPUT, of_port))
+ match.oxm_list.append(ofp.oxm.exp1ByteValue(ofp.oxm.OFDPA_EXP_TYPE_ALLOW_VLAN_TRANSLATION, 1))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+match_vlan,0x1fff))
+
+ actions=[]
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+inner_vlan)))
+ actions.append(ofp.action.push_vlan(0x8100))
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+outer_vlan)))
+
+ request = ofp.message.flow_add(
+ table_id=EGRESS_VLAN_FLOW_TABLE,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(EGRESS_DSCP_TABLE)
+ ],
+ priority=0)
+
+ ctrl.message_send(request)
+
+ return
+
+def 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):
+
+ # goto to table 20
+ if (flag == VLAN_TABLE_FLAG_ONLY_TAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH) or (flag == 4):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id,0x1fff))
+
+ actions=[]
+ if config["switch_type"] != 'xpliant' and vrf != 0:
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
+
+ #actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(value=vlan_id)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
+ ctrl.message_send(request)
+
+ if (flag == VLAN_TABLE_FLAG_ONLY_UNTAG) or (flag == VLAN_TABLE_FLAG_ONLY_BOTH):
+
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0, 0x1fff))
+
+ actions=[]
+ if vrf!=0:
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
+
+ # actions.append(ofp.action.push_vlan(0x8100))
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
+ ctrl.message_send(request)
+
+ if (flag == 4) :
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000,0x1fff))
+
+ actions=[]
+ if vrf!=0:
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf)))
+
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table 20" %( vlan_id, of_port))
+ ctrl.message_send(request)
+
+ if (flag == VLAN_TABLE_FLAG_ONLY_STACKED):
+ # This flag is meant to managed stacked vlan packtes
+ # Matches on outer VLAN_ID, set OVID with outer VLAN.
+ # Finally expose inner VLAN_ID with a pop action and
+ # goto VLAN_1_FLOW_TABLE
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id,0x1fff))
+
+ actions=[]
+ # actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_OVID, value=0x1000+vlan_id)))
+ actions.append(ofp.action.pop_vlan())
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_OVID, value=0x1000+vlan_id)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(VLAN_1_FLOW_TABLE)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table %d" %( vlan_id, of_port, VLAN_1_FLOW_TABLE))
+ ctrl.message_send(request)
+
+ if (flag == VLAN_TABLE_FLAG_PRIORITY) :
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000, 0x1fff))
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)),
+ ofp.action.push_vlan(0x8100),
+ ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+out_vlan_id)),
+ ]
+ ),
+ ofp.instruction.goto_table(20)
+ ],
+ priority=0)
+ logging.info("Add vlan %d untagged packets on port %d and go to table 20" % (vlan_id, of_port))
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def 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):
+ # table 10: vlan
+ # goto to table 13
+ if flag == VLAN_TABLE_FLAG_ONLY_TAG:
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+vlan_id, 0x1fff))
+
+ actions=[]
+ if vlan_id == -1:
+ actions.append(ofp.action.pop_vlan())
+ if new_vlan_id > 1:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_vlan_id)))
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
+ actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
+ # 0x0000nnnn is for UNI interfaces
+ actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(MPLS_L2_PORT_FLOW_TABLE)
+ ],
+ priority=0)
+ logging.info("Add vlan %d tagged packets on port %d and go to table %d" % (vlan_id, of_port, MPLS_L2_PORT_FLOW_TABLE))
+ ctrl.message_send(request)
+
+ if flag == VLAN_TABLE_FLAG_ONLY_UNTAG:
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0))
+
+ actions=[]
+ if vlan_id > 1:
+ # actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
+ # actions.append(ofp.action.set_field(ofp.action.push_vlan(0x8100)))
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vlan_id)))
+
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
+ actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
+ # 0x0000nnnn is for UNI interfaces
+ actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port)))
+
+ request = ofp.message.flow_add(
+ table_id=10,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(MPLS_L2_PORT_FLOW_TABLE)
+ ],
+ priority=0)
+ logging.info("Add vlan %d untagged packets on port %d and go to table %d" % (vlan_id, of_port, MPLS_L2_PORT_FLOW_TABLE))
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def 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):
+
+ # table 11: vlan 1 table
+ # goto to table 20
+ if flag == VLAN_TABLE_FLAG_ONLY_TAG:
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
+
+ actions=[]
+ actions.append(ofp.action.push_vlan(0x8100))
+ if new_outer_vlan_id != -1:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_outer_vlan_id)))
+ else:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+outer_vlan_id)))
+
+ request = ofp.message.flow_add(
+ table_id=11,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(TERMINATION_FLOW_TABLE)
+ ],
+ priority=0)
+ 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))
+ ctrl.message_send(request)
+
+ if flag == VLAN_TABLE_FLAG_ONLY_UNTAG:
+
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
+
+ actions=[]
+ request = ofp.message.flow_add(
+ table_id=11,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(TERMINATION_FLOW_TABLE)
+ ],
+ priority=0)
+ 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))
+ ctrl.message_send(request)
+
+ if flag == VLAN_TABLE_FLAG_ONLY_POP_VLAN:
+
+ print("INSTALLIN IN TABLE 11!")
+
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
+
+ actions=[]
+ actions.append(ofp.action.pop_vlan())
+
+ request = ofp.message.flow_add(
+ table_id=11,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(TERMINATION_FLOW_TABLE)
+ ],
+ priority=0)
+ 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))
+ ctrl.message_send(request)
+
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def 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):
+
+ # table 11: vlan 1 table
+ # goto to table 13
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(of_port))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(0x1000+inner_vlan_id,0x1fff))
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_OVID, 0x1000+outer_vlan_id))
+
+ actions=[]
+
+ if cross_connect:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+inner_vlan_id)))
+ actions.append(ofp.action.push_vlan(0x8100))
+ if new_outer_vlan_id != -1:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+new_outer_vlan_id)))
+ else:
+ actions.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+outer_vlan_id)))
+
+ if not cross_connect:
+ actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
+ actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
+ else:
+ actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE_CROSS_CONNECT)))
+
+ # 0x0000nnnn is for UNI interfaces
+ actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port)))
+
+ request = ofp.message.flow_add(
+ table_id=11,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ofp.instruction.goto_table(MPLS_L2_PORT_FLOW_TABLE)
+ ],
+ priority=0)
+ 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))
+ ctrl.message_send(request)
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_bridge_flow(ctrl, dst_mac, vlanid, group_id, send_barrier=False):
+ match = ofp.match()
+ priority=500
+ if dst_mac!=None:
+ priority=1000
+ match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
+
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
+
+ request = ofp.message.flow_add(
+ table_id=50,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[
+ ofp.action.group(group_id)]),
+ ofp.instruction.goto_table(60)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=priority)
+
+ logging.info("Inserting Brdige flow vlan %d, mac %s", vlanid, dst_mac)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_overlay_bridge_flow(ctrl, dst_mac, vnid, group_id, is_group=True, send_barrier=False):
+ match = ofp.match()
+ if dst_mac!=None:
+ match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
+
+ match.oxm_list.append(ofp.oxm.tunnel_id(vnid))
+ if is_group == True:
+ actions=[ofp.action.group(group_id)]
+ else:
+ actions=[ofp.action.output(group_id)]
+
+ request = ofp.message.flow_add(
+ table_id=50,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=actions),
+ ofp.instruction.goto_table(60)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1000)
+
+ logging.info("Inserting Brdige flow vnid %d, mac %s", vnid, dst_mac)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_termination_flow(ctrl, in_port, eth_type, dst_mac, vlanid, goto_table=None, send_barrier=False):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ if dst_mac[0]&0x01 == 0x01:
+ match.oxm_list.append(ofp.oxm.eth_dst_masked(dst_mac, [0xff, 0xff, 0xff, 0x80, 0x00, 0x00]))
+ goto_table=40
+ else:
+ if in_port!=0:
+ match.oxm_list.append(ofp.oxm.in_port(in_port))
+ match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
+ if goto_table == None:
+ goto_table=30
+
+ request = ofp.message.flow_add(
+ table_id=20,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.goto_table(goto_table)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+
+ logging.info("Inserting termination flow inport %d, eth_type %lx, vlan %d, mac %s", in_port, eth_type, vlanid, dst_mac)
+ ctrl.message_send(request)
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_unicast_routing_flow(ctrl, eth_type, dst_ip, mask, action_group_id, vrf=0, send_ctrl=False, send_barrier=False, priority = 1):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ if config["switch_type"] != 'xpliant' and vrf != 0:
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
+
+ match.oxm_list.append(ofp.oxm.ipv4_dst_masked(dst_ip, mask))
+
+ instructions = []
+ instructions.append(ofp.instruction.goto_table(60))
+ if send_ctrl:
+ instructions.append(ofp.instruction.write_actions(
+ actions=[ofp.action.output( port=ofp.OFPP_CONTROLLER,
+ max_len=ofp.OFPCML_NO_BUFFER)]))
+ else:
+ instructions.append(ofp.instruction.write_actions(
+ actions=[ofp.action.group(action_group_id)]))
+
+ request = ofp.message.flow_add(
+ table_id=30,
+ cookie=42,
+ match=match,
+ instructions=instructions,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=priority)
+
+ logging.info("Inserting unicast routing flow eth_type %lx, dip %ld",eth_type, dst_ip)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_unicast_blackhole_flow(ctrl, eth_type, dst_ip, mask, vrf=0, send_ctrl=False, send_barrier=False, priority = 1):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ if config["switch_type"] != 'xpliant' and vrf != 0:
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
+
+ match.oxm_list.append(ofp.oxm.ipv4_dst_masked(dst_ip, mask))
+
+ instructions = []
+ instructions.append(ofp.instruction.goto_table(60))
+ instructions.append(ofp.instruction.clear_actions( ))
+
+ request = ofp.message.flow_add(
+ table_id=30,
+ cookie=42,
+ match=match,
+ instructions=instructions,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=priority)
+
+ logging.info("Inserting unicast blackhole routing flow eth_type %lx, dip %ld",eth_type, dst_ip)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_unicast_v6_routing_flow(ctrl, eth_type, dst_ip, mask, action_group_id, vrf=0, send_ctrl=False, send_barrier=False):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ if vrf != 0:
+ match.oxm_list.append(ofp.oxm.exp2ByteValue(ofp.oxm.OFDPA_EXP_TYPE_VRF, vrf))
+
+ match.oxm_list.append(ofp.oxm.ipv6_dst_masked(parse_ipv6(dst_ip), parse_ipv6(mask)))
+
+ instructions = []
+ instructions.append(ofp.instruction.goto_table(60))
+ if send_ctrl:
+ instructions.append(ofp.instruction.write_actions(
+ actions=[ofp.action.output( port=ofp.OFPP_CONTROLLER,
+ max_len=ofp.OFPCML_NO_BUFFER)]))
+ else:
+ instructions.append(ofp.instruction.write_actions(
+ actions=[ofp.action.group(action_group_id)]))
+
+ request = ofp.message.flow_add(
+ table_id=30,
+ cookie=42,
+ match=match,
+ instructions=instructions,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+
+ logging.info("Inserting unicast routing flow eth_type %lx, dip %s",eth_type, dst_ip)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def 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):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(0x8847))
+ match.oxm_list.append(ofp.oxm.mpls_label(label))
+ match.oxm_list.append(ofp.oxm.mpls_bos(bos))
+ write_actions = []
+ write_actions.append(ofp.action.group(action_group_id))
+ apply_actions = []
+ apply_actions = [ofp.action.dec_mpls_ttl(),
+ ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=1, value=vrf))]
+ if (goto_table != 29):
+ apply_actions.append(ofp.action.set_field(
+ ofp.oxm.exp2ByteValue(exp_type=23, value=32)))
+ apply_actions.append(ofp.action.copy_ttl_in())
+
+ request = ofp.message.flow_add(
+ table_id=24,
+ cookie=43,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=apply_actions),
+ ofp.instruction.write_actions(actions=write_actions),
+ ofp.instruction.goto_table(goto_table)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def xpliant_add_mpls_flow(ctrl, action_group_id=0x0, label=100 ,ethertype=0x0800, bos=1, vrf=1, goto_table=27, send_barrier=False):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(0x8847))
+ match.oxm_list.append(ofp.oxm.mpls_label(label))
+
+ apply_actions = []
+ apply_actions.append(ofp.action.group(action_group_id))
+ apply_actions.append(ofp.action.dec_mpls_ttl())
+ if (goto_table != 29):
+ apply_actions.append(ofp.action.pop_mpls(ethertype))
+
+ request = ofp.message.flow_add(
+ table_id=24,
+ cookie=43,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=apply_actions),
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ logging.info("Inserting MPLS flow , label %ld", label)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_mpls_flow_swap(ctrl, action_group_id, label, ethertype, bos, goto_table=MPLS_TYPE_FLOW_TABLE, of_port=0, send_barrier=False):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(0x8847))
+ match.oxm_list.append(ofp.oxm.mpls_label(label))
+ match.oxm_list.append(ofp.oxm.mpls_bos(1))
+
+ apply_actions = []
+ write_actions = []
+ apply_actions.append(ofp.action.dec_mpls_ttl())
+ write_actions.append(ofp.action.group(action_group_id))
+
+ request = ofp.message.flow_add(
+ table_id=24,
+ cookie=43,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=apply_actions),
+ ofp.instruction.write_actions(actions=write_actions),
+ ofp.instruction.goto_table(goto_table)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+
+ logging.info("Inserting MPLS flow , label %ld", label)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+
+def 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):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(0x8847))
+ match.oxm_list.append(ofp.oxm.mpls_label(label))
+ match.oxm_list.append(ofp.oxm.mpls_bos(bos))
+
+ apply_actions = []
+ write_actions = []
+ apply_actions.append(ofp.action.dec_mpls_ttl())
+ if popMPLS == True:
+ apply_actions.append(ofp.action.copy_ttl_in())
+ apply_actions.append(ofp.action.pop_mpls(ethertype))
+ if bos==1 and popL2 == True:
+ apply_actions.append(ofp.action.ofdpa_pop_l2_header())
+ apply_actions.append(ofp.action.ofdpa_pop_cw())
+ apply_actions.append(ofp.action.set_field(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE)))
+ # 0x0002nnnn is for UNI interfaces
+ apply_actions.append(ofp.action.set_field(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00020000 + of_port)))
+ apply_actions.append(ofp.action.set_field(ofp.oxm.exp2ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_TYPE, value=ofp.oxm.VPWS)))
+
+ write_actions.append(ofp.action.group(action_group_id))
+
+ request = ofp.message.flow_add(
+ table_id=24,
+ cookie=43,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=apply_actions),
+ ofp.instruction.write_actions(actions=write_actions),
+ ofp.instruction.goto_table(goto_table)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ logging.info("Inserting MPLS flow , label %ld", label)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_mcast4_routing_flow(ctrl, vlan_id, src_ip, src_ip_mask, dst_ip, action_group_id, send_barrier=False):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(0x0800))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000 + vlan_id))
+ if src_ip_mask!=0:
+ match.oxm_list.append(ofp.oxm.ipv4_src_masked(src_ip, src_ip_mask))
+ else:
+ match.oxm_list.append(ofp.oxm.ipv4_src(src_ip))
+
+ match.oxm_list.append(ofp.oxm.ipv4_dst(dst_ip))
+
+ request = ofp.message.flow_add(
+ table_id=40,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[ofp.action.group(action_group_id)]),
+ ofp.instruction.goto_table(60)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+
+ logging.info("Inserting mcast routing flow eth_type %lx, dip %lx, sip %lx, sip_mask %lx",0x0800, dst_ip, src_ip, src_ip_mask)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+def add_acl_rule(ctrl, eth_type=None, ip_proto=None, vlan_id=None, send_barrier=False):
+ match = ofp.match()
+ if eth_type:
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ if ip_proto:
+ match.oxm_list.append(ofp.oxm.ip_proto(ip_proto))
+ if vlan_id:
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000 + vlan_id))
+ request = ofp.message.flow_add(
+ table_id=60,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[ofp.action.output(port=ofp.OFPP_CONTROLLER, max_len=ofp.OFPCML_NO_BUFFER)]
+ ),
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1
+ )
+ output = "Inserting ACL flow: "
+ if eth_type:
+ output += "eth_type {}, ".format(eth_type)
+ if ip_proto:
+ output += "ip_proto {}, ".format(ip_proto)
+ if vlan_id:
+ output += "vlan_id {}".format(vlan_id)
+ logging.info(output)
+
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return request
+
+#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
+def add_dnat_flow(ctrl, eth_type, ip_dst, ip_proto, tcp_dst, set_ip_dst, set_tcp_dst, action_group_id):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ match.oxm_list.append(ofp.oxm.ipv4_dst(ip_dst))
+ match.oxm_list.append(ofp.oxm.ip_proto(ip_proto))
+ match.oxm_list.append(ofp.oxm.tcp_dst(tcp_dst))
+
+ request = ofp.message.flow_add(
+ table_id=28,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[ofp.action.set_field(ofp.oxm.ipv4_dst(set_ip_dst)),
+ ofp.action.set_field(ofp.oxm.tcp_dst(set_tcp_dst)),
+ ofp.action.group(action_group_id)]),
+ ofp.instruction.goto_table(60)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ 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)
+ ctrl.message_send(request)
+ return request
+
+#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
+def add_snat_flow(ctrl, eth_type, ip_src, ip_proto, tcp_src, set_ip_src, set_tcp_src):
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.eth_type(eth_type))
+ match.oxm_list.append(ofp.oxm.ipv4_src(ip_src))
+ match.oxm_list.append(ofp.oxm.ip_proto(ip_proto))
+ match.oxm_list.append(ofp.oxm.tcp_src(tcp_src))
+
+ request = ofp.message.flow_add(
+ table_id=29,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[ofp.action.set_field(ofp.oxm.ipv4_src(set_ip_src)),
+ ofp.action.set_field(ofp.oxm.tcp_src(set_tcp_src))]),
+ ofp.instruction.goto_table(30)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ 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)
+ ctrl.message_send(request)
+ return request
+
+def get_vtap_lport_config_xml(dp_id, lport, phy_port, vlan, vnid, operation='merge'):
+ """
+ Command Example:
+ of-agent vtap 10001 ethernet 1/1 vid 1
+ of-agent vtp 10001 vni 10
+ """
+ if vlan != 0:
+ config_vtap_xml="""
+ <config>
+ <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <id>capable-switch-1</id>
+ <resources>
+ <port xc:operation="OPERATION">
+ <resource-id >LPORT</resource-id>
+ <features>
+ <current>
+ <rate>10Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </current>
+ <advertised>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </advertised>
+ <supported>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </supported>
+ <advertised-peer>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </advertised-peer>
+ </features>
+ <ofdpa10:vtap xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
+ <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
+ <ofdpa10:vid>VLAN_ID</ofdpa10:vid>
+ <ofdpa10:vni>VNID</ofdpa10:vni>
+ </ofdpa10:vtap>
+ </port>
+ </resources>
+ <logical-switches>
+ <switch>
+ <id>DATAPATH_ID</id>
+ <datapath-id>DATAPATH_ID</datapath-id>
+ <resources>
+ <port xc:operation="OPERATION">LPORT</port>
+ </resources>
+ </switch>
+ </logical-switches>
+ </capable-switch>
+ </config>
+ """
+ else:
+ config_vtap_xml="""
+ <config>
+ <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <id>capable-switch-1</id>
+ <resources>
+ <port xc:operation="OPERATION">
+ <resource-id >LPORT</resource-id>
+ <features>
+ <current>
+ <rate>10Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </current>
+ <advertised>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </advertised>
+ <supported>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </supported>
+ <advertised-peer>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </advertised-peer>
+ </features>
+ <ofdpa10:vtap xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
+ <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
+ <ofdpa10:vni>VNID</ofdpa10:vni>
+ </ofdpa10:vtap>
+ </port>
+ </resources>
+ <logical-switches>
+ <switch>
+ <id>DATAPATH_ID</id>
+ <datapath-id>DATAPATH_ID</datapath-id>
+ <resources>
+ <port xc:operation="OPERATION">LPORT</port>
+ </resources>
+ </switch>
+ </logical-switches>
+ </capable-switch>
+ </config>
+ """
+ str_datapath_id_f= "{:016x}".format(dp_id)
+ str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
+ config_vtap_xml=config_vtap_xml.replace("DATAPATH_ID", str_datapath_id)
+ config_vtap_xml=config_vtap_xml.replace("LPORT", str(int(lport)))
+ config_vtap_xml=config_vtap_xml.replace("PHY_PORT", str(phy_port))
+ config_vtap_xml=config_vtap_xml.replace("VLAN_ID", str(vlan))
+ config_vtap_xml=config_vtap_xml.replace("VNID", str(vnid))
+ config_vtap_xml=config_vtap_xml.replace("OPERATION", str(operation))
+ return config_vtap_xml
+
+def get_vtep_lport_config_xml(dp_id, lport, src_ip, dst_ip, next_hop_id, vnid, udp_src_port=6633, ttl=25, operation='merge'):
+ """
+ Command Example:
+ of-agent vtep 10002 source user-input-src-ip destination user-input-dst-ip udp-source-port 6633 nexthop 2 ttl 25
+ of-agent vtp 10001 vni 10
+ """
+
+ config_vtep_xml="""
+ <config>
+ <capable-switch xmlns="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <id>capable-switch-1</id>
+ <resources>
+ <port xc:operation="OPERATION">
+ <resource-id>LPORT</resource-id>
+ <features>
+ <current>
+ <rate>10Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </current>
+ <advertised>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </advertised>
+ <supported>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </supported>
+ <advertised-peer>
+ <rate>10Gb</rate>
+ <rate>100Gb</rate>
+ <medium>fiber</medium>
+ <pause>symmetric</pause>
+ </advertised-peer>
+ </features>
+ <ofdpa10:vtep xmlns:ofdpa10="urn:bcm:ofdpa10:accton01">
+ <ofdpa10:src-ip>SRC_IP</ofdpa10:src-ip>
+ <ofdpa10:dest-ip>DST_IP</ofdpa10:dest-ip>
+ <ofdpa10:udp-src-port>UDP_SRC_PORT</ofdpa10:udp-src-port>
+ <ofdpa10:vni xc:operation="OPERATION">
+ <ofdpa10:id>VNID</ofdpa10:id>
+ </ofdpa10:vni>
+ <ofdpa10:nexthop-id>NEXT_HOP_ID</ofdpa10:nexthop-id>
+ <ofdpa10:ttl>TTL</ofdpa10:ttl>
+ </ofdpa10:vtep>
+ </port>
+ </resources>
+ <logical-switches>
+ <switch>
+ <id>DATAPATH_ID</id>
+ <datapath-id>DATAPATH_ID</datapath-id>
+ <resources>
+ <port xc:operation="OPERATION">LPORT</port>
+ </resources>
+ </switch>
+ </logical-switches>
+ </capable-switch>
+ </config>
+ """
+ str_datapath_id_f= "{:016x}".format(dp_id)
+ str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
+ config_vtep_xml=config_vtep_xml.replace("DATAPATH_ID", str_datapath_id)
+ config_vtep_xml=config_vtep_xml.replace("LPORT", str(int(lport)))
+ config_vtep_xml=config_vtep_xml.replace("SRC_IP", str(src_ip))
+ config_vtep_xml=config_vtep_xml.replace("DST_IP", str(dst_ip))
+ config_vtep_xml=config_vtep_xml.replace("UDP_SRC_PORT", str(udp_src_port))
+ config_vtep_xml=config_vtep_xml.replace("NEXT_HOP_ID", str(next_hop_id))
+ config_vtep_xml=config_vtep_xml.replace("TTL", str(ttl))
+ config_vtep_xml=config_vtep_xml.replace("VNID", str(vnid))
+ config_vtep_xml=config_vtep_xml.replace("OPERATION", str(operation))
+
+ return config_vtep_xml
+
+def get_next_hop_config_xml(next_hop_id, dst_mac, phy_port, vlan, operation='merge'):
+ #of-agent nexthop 2 destination user-input-dst-mac ethernet 1/2 vid 2
+ config_nexthop_xml="""
+ <config>
+ <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <ofdpa10:next-hop xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
+ <ofdpa10:id>NEXT_HOP_ID</ofdpa10:id>
+ <ofdpa10:dest-mac>DST_MAC</ofdpa10:dest-mac>
+ <ofdpa10:phy-port>PHY_PORT</ofdpa10:phy-port>
+ <ofdpa10:vid>VLAN_ID</ofdpa10:vid>
+ </ofdpa10:next-hop>
+ </of11-config:capable-switch>
+ </config>
+ """
+ config_nexthop_xml=config_nexthop_xml.replace("VLAN_ID", str(vlan))
+ config_nexthop_xml=config_nexthop_xml.replace("PHY_PORT", str(phy_port))
+ config_nexthop_xml=config_nexthop_xml.replace("NEXT_HOP_ID", str(next_hop_id))
+ config_nexthop_xml=config_nexthop_xml.replace("DST_MAC", str(dst_mac))
+ config_nexthop_xml=config_nexthop_xml.replace("OPERATION", str(operation))
+ return config_nexthop_xml
+
+def get_vni_config_xml(vni_id, mcast_ipv4, next_hop_id, operation='merge'):
+ #of-agent vni 10 multicast 224.1.1.1 nexthop 20
+ if mcast_ipv4!=None:
+ config_vni_xml="""
+ <config>
+ <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <ofdpa10:vni xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
+ <ofdpa10:id>VNID</ofdpa10:id>
+ <ofdpa10:vni-multicast-group>MCAST_IP</ofdpa10:vni-multicast-group>
+ <ofdpa10:multicast-group-nexthop-id>NEXT_HOP_ID</ofdpa10:multicast-group-nexthop-id>
+ </ofdpa10:vni>
+ </of11-config:capable-switch>
+ </config>
+ """
+ config_vni_xml=config_vni_xml.replace("NEXT_HOP_ID", str(next_hop_id))
+ config_vni_xml=config_vni_xml.replace("MCAST_IP", str(mcast_ipv4))
+ else:
+ config_vni_xml="""
+ <config>
+ <of11-config:capable-switch xmlns:of11-config="urn:onf:of111:config:yang" xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <ofdpa10:vni xmlns:ofdpa10="urn:bcm:ofdpa10:accton01" xc:operation="OPERATION">
+ <ofdpa10:id>VNID</ofdpa10:id>
+ </ofdpa10:vni>
+ </of11-config:capable-switch>
+ </config>
+ """
+
+ config_vni_xml=config_vni_xml.replace("VNID", str(vni_id))
+ config_vni_xml=config_vni_xml.replace("OPERATION", str(operation))
+ return config_vni_xml
+
+def get_featureReplay(self):
+ req = ofp.message.features_request()
+ res, raw = self.controller.transact(req)
+ self.assertIsNotNone(res, "Did not receive a response from the DUT.")
+ self.assertEqual(res.type, ofp.OFPT_FEATURES_REPLY,
+ ("Unexpected packet type %d received in response to "
+ "OFPT_FEATURES_REQUEST") % res.type)
+ return res
+
+def send_edit_config(switch_ip, xml, target='runing'):
+ NETCONF_ACCOUNT="netconfuser"
+ NETCONF_PASSWD="netconfuser"
+ with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
+ try:
+ m.edit_config(target='running',
+ config=xml,
+ default_operation='merge',
+ error_option='stop-on-error')
+
+ except Exception as e:
+ logging.info("Fail to set xml %s", xml)
+ return False
+
+ #return m.get_config(source='running').data_xml
+ return True
+
+def send_delete_config(switch_ip, xml, target='runing'):
+ NETCONF_ACCOUNT="netconfuser"
+ NETCONF_PASSWD="netconfuser"
+ with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
+ try:
+ m.edit_config(target='running',
+ config=xml,
+ default_operation='delete',
+ error_option='stop-on-error')
+
+ except Exception as e:
+ logging.info("Fail to set xml %s", xml)
+ return False
+
+ #return m.get_config(source='running').data_xml
+ return True
+
+def get_edit_config(switch_ip, target='runing'):
+ NETCONF_ACCOUNT="netconfuser"
+ NETCONF_PASSWD="netconfuser"
+ with manager.connect_ssh(host=switch_ip, port=830, username=NETCONF_ACCOUNT, password=NETCONF_PASSWD, hostkey_verify=False ) as m:
+ return m.get_config(source='running').data_xml
+
+
+"""
+MPLS
+"""
+
+OFDPA_MPLS_SUBTYPE_SHIFT=24
+OFDPA_MPLS_GROUP_SUBTYPE_L2_VPN_LABEL=1
+OFDPA_MPLS_GROUP_SUBTYPE_L3_VPN_LABEL=2
+OFDPA_MPLS_GROUP_SUBTYPE_TUNNEL_LABEL1=3
+OFDPA_MPLS_GROUP_SUBTYPE_TUNNEL_LABEL2=4
+OFDPA_MPLS_GROUP_SUBTYPE_SWAP_LABEL=5
+OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP=6
+OFDPA_MPLS_GROUP_SUBTYPE_ECMP=8
+OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG=10
+
+
+
+
+def encode_mpls_interface_group_id(subtype, index):
+ index=index&0x00ffffff
+ assert(subtype==0)
+ return index + (9 << OFDPA_GROUP_TYPE_SHIFT)+(subtype<<OFDPA_MPLS_SUBTYPE_SHIFT)
+
+def encode_mpls_label_group_id(subtype, index):
+ index=index&0x00ffffff
+ assert(subtype <=5 or subtype==0)
+ #1: l2 vpn label
+ #2: l3 vpn label
+ #3: mpls tunnel label 1
+ #4: mpls tunnel lable 2
+ #5: mpls swap label
+ return index + (9 << OFDPA_GROUP_TYPE_SHIFT)+(subtype<<OFDPA_MPLS_SUBTYPE_SHIFT)
+
+def encode_mpls_forwarding_group_id(subtype, index):
+ index=index&0x00ffffff
+ assert(subtype==6 or subtype==8 or subtype==10)
+ return index + (10 << OFDPA_GROUP_TYPE_SHIFT)+(subtype<<OFDPA_MPLS_SUBTYPE_SHIFT)
+
+
+def add_mpls_intf_group(ctrl, ref_gid, dst_mac, src_mac, vid, index, subtype=0, send_barrier=False, add=True):
+ action=[]
+ action.append(ofp.action.set_field(ofp.oxm.eth_src(src_mac)))
+ action.append(ofp.action.set_field(ofp.oxm.eth_dst(dst_mac)))
+ action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+vid)))
+ action.append(ofp.action.group(ref_gid))
+
+ buckets = [ofp.bucket(actions=action)]
+
+ mpls_group_id =encode_mpls_interface_group_id(subtype, index)
+ if add:
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=mpls_group_id,
+ buckets=buckets
+ )
+ else:
+ request = ofp.message.group_modify(group_type=ofp.OFPGT_INDIRECT,
+ group_id=mpls_group_id,
+ buckets=buckets
+ )
+
+
+ logging.debug("Adding MPLS interface group %02x, src_mac %s , dst_mac %s , vid %d", mpls_group_id, src_mac, dst_mac, vid)
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+ return mpls_group_id, request
+
+def add_mpls_tunnel_label_group(
+ ctrl,
+ ref_gid,
+ subtype,
+ index,
+ label,
+ ):
+
+ action=[]
+ action.append(ofp.action.push_mpls(0x8847))
+ action.append(ofp.action.set_field(ofp.oxm.mpls_label(label)))
+ action.append(ofp.action.group(ref_gid))
+ buckets = [ofp.bucket(actions=action)]
+
+ mpls_group_id = encode_mpls_label_group_id(subtype, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=mpls_group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ return mpls_group_id, request
+
+def add_mpls_swap_label_group(
+ ctrl,
+ ref_gid,
+ subtype,
+ index,
+ label,
+ ):
+
+ action=[]
+ action.append(ofp.action.set_field(ofp.oxm.mpls_label(label)))
+ action.append(ofp.action.group(ref_gid))
+ buckets = [ofp.bucket(actions=action)]
+
+ mpls_group_id = encode_mpls_label_group_id(subtype, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=mpls_group_id,
+ buckets=buckets
+ )
+ logging.debug("Adding MPLS Swap group %02x, label %d", mpls_group_id, label)
+ ctrl.message_send(request)
+
+ return mpls_group_id, request
+
+def add_mpls_label_group(ctrl, subtype, index, ref_gid,
+ lmep_id=-1,
+ qos_index=-1,
+ push_l2_header=False,
+ push_vlan=False,
+ push_mpls_header=False,
+ push_cw=False,
+ set_mpls_label=None,
+ set_bos=None,
+ set_tc=None,
+ set_tc_from_table=False,
+ cpy_tc_outward=False,
+ set_ttl=None,
+ cpy_ttl_outward=False,
+ oam_lm_tx_count=False,
+ set_pri_from_table=False,
+ send_barrier=False
+ ):
+ """
+ @ref_gid: only can be mpls intf group or mpls tunnel label 1/2 group
+ """
+ action=[]
+
+ if push_vlan== True:
+ action.append(ofp.action.push_vlan(0x8100))
+ if push_mpls_header== True:
+ action.append(ofp.action.push_mpls(0x8847))
+ if set_mpls_label != None:
+ action.append(ofp.action.set_field(ofp.oxm.mpls_label(set_mpls_label)))
+ if set_bos != None:
+ action.append(ofp.action.set_field(ofp.oxm.mpls_bos(set_bos)))
+ if set_tc != None:
+ assert(set_tc_from_table==False)
+ action.append(ofp.action.set_field(ofp.oxm.mpls_tc(set_tc)))
+ if set_ttl != None:
+ action.append(ofp.action.set_mpls_ttl(set_ttl))
+ if cpy_ttl_outward == True:
+ action.append(ofp.action.copy_ttl_out())
+ """
+ ofdpa experimenter
+ """
+ if push_l2_header== True:
+ action.append(ofp.action.ofdpa_push_l2_header())
+ if set_tc_from_table== True:
+ assert(qos_index>=0)
+ assert(set_tc == None)
+ action.append(ofp.action.ofdpa_set_tc_from_table(qos_index))
+ if cpy_tc_outward == True:
+ action.append(ofp.action.ofdpa_copy_tc_out())
+ if oam_lm_tx_count == True:
+ assert(qos_index>=0 and lmep_id>=0)
+ action.append(ofp.action.ofdpa_oam_lm_tx_count(lmep_id, qos_index))
+ if set_pri_from_table == True:
+ assert(qos_index>=0)
+ action.append(ofp.action.ofdpa_set_qos_from_table(qos_index))
+ if push_cw == True:
+ action.append(ofp.action.ofdpa_push_cw())
+
+ action.append(ofp.action.group(ref_gid))
+ buckets = [ofp.bucket(actions=action)]
+
+ mpls_group_id = encode_mpls_label_group_id(subtype, index)
+ request = ofp.message.group_add(group_type=ofp.OFPGT_INDIRECT,
+ group_id=mpls_group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+
+ if send_barrier:
+ do_barrier(ctrl)
+
+ return mpls_group_id, request
+
+def 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):
+ """
+ Only action is Group, which must indicate one of:
+ MPLS L2 VPN Label or Fast Failover Protection Group.
+ ref_gid contains this information
+ """
+
+ match = ofp.match()
+
+ write_actions = []
+ write_actions.append(ofp.action.group(ref_gid))
+ apply_actions = []
+
+ if goto==MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE:
+ tunnel_id = tunnel_index + ofp.oxm.TUNNEL_ID_BASE
+ match.oxm_list.append(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port))
+ match.oxm_list.append(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE))
+ assert(qos_index>=0)
+ apply_actions.append(ofp.action.set_field(ofp.oxm.exp1ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_QOS_INDEX, value=qos_index)))
+
+ request = ofp.message.flow_add(
+ table_id=MPLS_L2_PORT_FLOW_TABLE,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=apply_actions),
+ ofp.instruction.write_actions(actions=write_actions),
+ ofp.instruction.goto_table(goto)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ 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)
+ ctrl.message_send(request)
+
+ if goto==ACL_FLOW_TABLE:
+ tunnel_id = tunnel_index + ofp.oxm.TUNNEL_ID_BASE
+ match.oxm_list.append(ofp.oxm.exp4ByteValue(exp_type=ofp.oxm.OFDPA_EXP_TYPE_MPLS_L2_PORT, value=0x00000000 + of_port))
+ match.oxm_list.append(ofp.oxm.tunnel_id(tunnel_index + ofp.oxm.TUNNEL_ID_BASE_CROSS_CONNECT))
+ request = ofp.message.flow_add(
+ table_id=MPLS_L2_PORT_FLOW_TABLE,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(actions=apply_actions),
+ ofp.instruction.write_actions(actions=write_actions),
+ ofp.instruction.goto_table(goto)
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+ 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)
+ ctrl.message_send(request)
+
+ return request
+
+def add_mpls_forwarding_group(ctrl, subtype, index, ref_gids,
+ watch_port=None,
+ watch_group=ofp.OFPP_ANY,
+ push_vlan=None,
+ pop_vlan=None,
+ set_vid=None):
+ assert(subtype == OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP
+ or subtype == OFDPA_MPLS_GROUP_SUBTYPE_ECMP
+ or subtype == OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG)
+
+ buckets=[]
+ if subtype == OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP:
+ group_type = ofp.OFPGT_FF
+ for gid in ref_gids:
+ action=[]
+ action.append(ofp.action.group(gid))
+ buckets.append(ofp.bucket(watch_port=watch_port, watch_group=watch_group,actions=action))
+
+ elif subtype == OFDPA_MPLS_GROUP_SUBTYPE_ECMP:
+ group_type = ofp.OFPGT_SELECT
+ for gid in ref_gids:
+ action=[]
+ action.append(ofp.action.group(gid))
+ buckets.append(ofp.bucket(actions=action))
+
+ elif subtype == OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG:
+ group_type = ofp.OFPGT_INDIRECT
+ action=[]
+ if set_vid!=None:
+ action.append(ofp.action.set_field(ofp.oxm.vlan_vid(0x1000+set_vid)))
+ if push_vlan!=None:
+ action.append(ofp.action.push_vlan(push_vlan))
+ if pop_vlan!=None:
+ action.append(ofp.action.pop_vlan())
+ action.append(ofp.action.group(ref_gids[0]))
+ buckets.append(ofp.bucket(actions=action))
+
+ mpls_group_id = encode_mpls_forwarding_group_id(subtype, index)
+ request = ofp.message.group_add(group_type=group_type,
+ group_id=mpls_group_id,
+ buckets=buckets
+ )
+ ctrl.message_send(request)
+ return mpls_group_id, request
+
+def add_one_egress_vlan_tpid_table_flow(ctrl, of_port):
+ # Used for changing ethertype of outer vlan header to 0x88a8
+
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.exp4ByteValue(ofp.oxm.OFDPA_EXP_TYPE_ACTSET_OUTPUT, of_port, ONF_EXPERIMENTER_ID))
+ match.oxm_list.append(ofp.oxm.vlan_vid_masked(ofp.OFPVID_PRESENT, ofp.OFPVID_PRESENT))
+
+ actions = []
+ actions.append(ofp.action.copy_field(
+ 12, 0, 0, ['\x80\x00\x0c\x02', ofp.oxm.exp4ByteReg(oxm_field = 1).pack()])) # VLAN_VID, PACKET_REG(1)
+ actions.append(ofp.action.pop_vlan())
+ actions.append(ofp.action.push_vlan(0x88a8))
+ actions.append(ofp.action.copy_field(
+ 12, 0, 0, [ofp.oxm.exp4ByteReg(oxm_field = 1).pack(), '\x80\x00\x0c\x02'])) # PACKET_REG(1), VLAN_VID
+
+ request = ofp.message.flow_add(
+ table_id=EGRESS_TPID_FLOW_TABLE,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=actions
+ ),
+ ],
+ priority=0)
+
+ ctrl.message_send(request)
+
+ return
+
+"""
+display
+"""
+def print_current_table_flow_stat(ctrl, table_id=0xff):
+ stat_req=ofp.message.flow_stats_request()
+ response, pkt = ctrl.transact(stat_req)
+ if response == None:
+ print "no response"
+ return None
+ print len(response.entries)
+ for obj in response.entries:
+ print "match ", obj.match
+ print "cookie", obj.cookie
+ print "priority", obj.priority
+ print "idle_timeout", obj.idle_timeout
+ print "hard_timeout", obj.hard_timeout
+ #obj.actions
+ print "packet count: %lx"%obj.packet_count
+
diff --git a/Fabric/Utilities/accton/acl_flow.py b/Fabric/Utilities/accton/acl_flow.py
new file mode 100755
index 0000000..c055ba1
--- /dev/null
+++ b/Fabric/Utilities/accton/acl_flow.py
@@ -0,0 +1,71 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+from oftest.testutils import *
+from accton_util import *
+
+
+class NoVlanOnlyAclOutputPort(base_tests.SimpleDataPlane):
+ """
+ In OFDPA, ACL can save the packet it was dropped vlan table
+ """
+ def runTest(self):
+ ports = sorted(config["port_map"].keys())
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ input_port=ports[0]
+ output_port=ports[1]
+ vlan_id = 10
+ dmac = [0x00, 0x12, 0x34, 0x56, 0x78, 0x9a]
+ gid, req_msg = add_one_l2_interface_group(self.controller, port=output_port, vlan_id=vlan_id, is_tagged=True, send_barrier=False)
+ #add ACL flow to output port
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(input_port))
+ match.oxm_list.append(ofp.oxm.eth_dst(dmac))
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlan_id))
+ request = ofp.message.flow_add(
+ table_id=60,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[
+ ofp.action.group(gid)]
+ )
+ ],
+ priority=1)
+ #install flow
+ self.controller.message_send(request)
+
+ dmac_str = convertMACtoStr(dmac)
+ #send packet
+ parsed_pkt = simple_tcp_packet(eth_dst=dmac_str, vlan_vid=vlan_id, dl_vlan_enable=True)
+ self.dataplane.send(input_port, str(parsed_pkt))
+ #verify packet
+ verify_packet(self, str(parsed_pkt), output_port)
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Fabric/Utilities/accton/epr.py b/Fabric/Utilities/accton/epr.py
new file mode 100755
index 0000000..c13a3d7
--- /dev/null
+++ b/Fabric/Utilities/accton/epr.py
@@ -0,0 +1,105 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+from oftest.testutils import *
+from accton_util import *
+
+"""
+This file test case is copied from NTC EPR bug
+"""
+
+class pvidClear(base_tests.SimpleDataPlane):
+ """
+ AOS5700-54X-00620
+ """
+ def runTest(self):
+ ports = sorted(config["port_map"].keys())
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ port1=ports[0]
+ port2=ports[1]
+
+ vlan_id = 10
+
+ gid_p1, req_msg_p1 = add_one_l2_interface_group(self.controller, port=port1, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ gid_p2, req_msg_p2 = add_one_l2_interface_group(self.controller, port=port2, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ #add ACL flow, in port1 out port2
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(port1))
+ request = ofp.message.flow_add(
+ table_id=60,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[
+ ofp.action.group(gid_p2)]
+ )
+ ],
+ priority=1)
+ #install flow
+ self.controller.message_send(request)
+ #add ACL flow, in port2 out port1
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(port2))
+ request = ofp.message.flow_add(
+ table_id=60,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[
+ ofp.action.group(gid_p1)]
+ )
+ ],
+ priority=1)
+ #install flow
+ self.controller.message_send(request)
+
+ #send packet and verify packet
+ parsed_pkt = simple_tcp_packet()
+ self.dataplane.send(port1, str(parsed_pkt))
+ verify_no_packet(self, str(parsed_pkt), port2)
+ self.dataplane.send(port2, str(parsed_pkt))
+ verify_no_packet(self, str(parsed_pkt), port1)
+
+
+ #add vlan flow table
+ add_vlan_table_flow(self.controller, [port1, port2], vlan_id=vlan_id, flag=VLAN_TABLE_FLAG_ONLY_UNTAG)
+ #send packet and verify packet
+ parsed_pkt = simple_tcp_packet()
+ self.dataplane.send(port1, str(parsed_pkt))
+ verify_packet(self, str(parsed_pkt), port2)
+ self.dataplane.send(port2, str(parsed_pkt))
+ verify_packet(self, str(parsed_pkt), port1)
+
+ #remove vlan table flow
+ del_vlan_table_flow(self.controller, [port1, port2], vlan_id=vlan_id, flag=VLAN_TABLE_FLAG_ONLY_UNTAG)
+ #send packet and verify packet
+ parsed_pkt = simple_tcp_packet()
+ self.dataplane.send(port1, str(parsed_pkt))
+ verify_no_packet(self, str(parsed_pkt), port2)
+ self.dataplane.send(port2, str(parsed_pkt))
+ verify_no_packet(self, str(parsed_pkt), port1)
+
+
+
+
diff --git a/Fabric/Utilities/accton/flow_test.py b/Fabric/Utilities/accton/flow_test.py
new file mode 100755
index 0000000..348d8ab
--- /dev/null
+++ b/Fabric/Utilities/accton/flow_test.py
@@ -0,0 +1,1040 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+Flow Test
+
+Test each flow table can set entry, and packet rx correctly.
+"""
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+from oftest.testutils import *
+from accton_util import *
+
+class L2McastFlow(base_tests.SimpleDataPlane):
+ """
+ Test output function for an exact-match flow
+
+ Add some multicast flows
+ Then, for all ports, verifies that sending a matching packet
+ to a multicast match results in an output to all ports.
+ """
+ def runTest(self):
+ ports = sorted(config["port_map"].keys())
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ # table 10: vlan
+ # send to table 20
+ add_vlan_table_flow(self.controller, config["port_map"].keys(), 1)
+
+ # group table
+ # set up untag groups for each port
+ add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+
+ # set up multicast group
+ add_l2_mcast_group(self.controller, config["port_map"].keys(), 1, 1)
+
+ test_macs = [[0x01, 0x00, 0x5e, 0x0f, 0xff, 0xff]]
+
+ for test_mac in test_macs:
+ group_id = encode_l2_mcast_group_id(1, 1)
+ add_bridge_flow(self.controller, test_mac, 1, group_id, True)
+
+ for test_mac in test_macs:
+ mactest = ':'.join(['%02X' % x for x in test_mac])
+
+ for in_port in ports:
+ # change dest based on port number
+ parsed_pkt = simple_tcp_packet(eth_dst=mactest)
+ pkt = str(parsed_pkt)
+ logging.info("OutputExact test, from port %d to mac %s", in_port, mactest)
+ self.dataplane.send(in_port, pkt)
+
+ for ofport in ports:
+ if ofport == in_port: #tx port won't rx packet, unless L3 mcast routing
+ continue
+ verify_packet(self, pkt, ofport)
+ verify_no_other_packets(self)
+
+class L2UnicastFlow(base_tests.SimpleDataPlane):
+ """
+ Test output function for an exact-match flow
+
+ For each port A, adds a flow directing matching packets to that port.
+ Then, for all other ports B != A, verifies that sending a matching packet
+ to B results in an output to A.
+ """
+ def runTest(self):
+ ports = sorted(config["port_map"].keys())
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ # table 10: vlan
+ # send to table 20
+ #add_vlan_table_flow(self.controller, config["port_map"].keys(),1)
+
+ # group table
+ # set up tag groups for each port
+ add_l2_interface_group(self.controller, config["port_map"].keys(), 1, True, 1)
+
+ for port in ports:
+ add_one_vlan_table_flow(self.controller, port, 1)
+ group_id = encode_l2_interface_group_id(1, port)
+ add_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, port], 1, group_id, True)
+ do_barrier(self.controller)
+
+ for out_port in ports:
+ # change dest based on port number
+ mac_dst= '00:12:34:56:78:%02X' % out_port
+
+ for in_port in ports:
+ if in_port == out_port:
+ continue
+ # change source based on port number to avoid packet-ins from learning
+ mac_src= '00:12:34:56:79:%02X' % in_port
+ parsed_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=1, eth_dst=mac_dst, eth_src=mac_src)
+ pkt = str(parsed_pkt)
+ logging.info("OutputExact test, ports %d to %d", in_port, out_port)
+ self.dataplane.send(in_port, pkt)
+
+ for ofport in ports:
+ if ofport in [out_port]:
+ verify_packet(self, pkt, ofport)
+ else:
+ verify_no_packet(self, pkt, ofport)
+
+ verify_no_other_packets(self)
+
+class L2Flood(base_tests.SimpleDataPlane):
+ """
+ Test L2 unknown unicast flooding and broadcast flood
+ """
+ def runTest(self):
+ ports = sorted(config["port_map"].keys())
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ # table 10: vlan
+ # send to table 20
+ add_vlan_table_flow(self.controller, ports, 1)
+
+ # group table
+ # set up untag groups for each port
+ add_l2_interface_grouop(self.controller, ports, 1, False, 1)
+
+ input_port = ports.pop()
+ flood_ports= ports
+
+ #no fllod group create, veriy all drop
+ parsed_pkt = simple_tcp_packet(eth_dst='00:12:34:56:78:9a')
+ pkt = str(parsed_pkt)
+ self.dataplane.send(input_port, pkt)
+ verify_no_other_packets(self)
+ parsed_pkt = simple_tcp_packet(eth_dst='FF:FF:FF:FF:FF:FF')
+ pkt = str(parsed_pkt)
+ self.dataplane.send(input_port, pkt)
+ verify_no_other_packets(self)
+ #add flood groupo
+ msg=add_l2_flood_group(self.controller, flood_ports, 1, 1)
+ add_bridge_flow(self.controller, None, 1, msg.group_id, True)
+ #verify flood
+ parsed_pkt = simple_tcp_packet(eth_dst='00:12:34:56:78:9a')
+ pkt = str(parsed_pkt)
+ self.dataplane.send(input_port, pkt)
+ for ofport in flood_ports:
+ verify_packet(self, pkt, ofport)
+
+ verify_no_other_packets(self)
+
+ for ofport in flood_ports:
+ self.dataplane.send(ofport, pkt)
+ #self won't rx packet
+ verify_no_packet(self, pkt, ofport)
+ #others will rx packet
+ tmp_ports=[]
+ for tmp in flood_ports:
+ if tmp != ofport:
+ tmp_ports.append(tmp)
+ verify_packets(self, pkt, tmp_ports)
+
+ verify_no_other_packets(self)
+
+ parsed_pkt = simple_tcp_packet(eth_dst='FF:FF:FF:FF:FF:FF')
+ pkt = str(parsed_pkt)
+ self.dataplane.send(input_port, pkt)
+ for ofport in flood_ports:
+ verify_packet(self, pkt, ofport)
+
+class PacketInMiss(base_tests.SimpleDataPlane):
+ """
+ Test packet in function for a table-miss flow
+
+ Send a packet to each dataplane port and verify that a packet
+ in message is received from the controller for each
+
+ NOTE: Verify This case the oft option shall not use --switch-ip
+ """
+
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ parsed_pkt = simple_tcp_packet(pktlen=100)
+ parsed_vlan_pkt = simple_tcp_packet(pktlen=104,
+ vlan_vid=0x1001, dl_vlan_enable=True)
+ pkt = str(parsed_pkt)
+ vlan_pkt = str(parsed_vlan_pkt)
+ # table 10: vlan
+ # send to table 20
+ add_vlan_table_flow(self.controller, config["port_map"].keys(), 1)
+
+ # group table
+ # set up untag groups for each port
+ add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, 1)
+
+ # create match
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.vlan_vid(0x1001))
+ request = ofp.message.flow_add(
+ table_id=60,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.apply_actions(
+ actions=[
+ ofp.action.output(
+ port=ofp.OFPP_CONTROLLER,
+ max_len=ofp.OFPCML_NO_BUFFER)]),
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1)
+
+ logging.info("Inserting packet in flow to controller")
+ self.controller.message_send(request)
+ do_barrier(self.controller)
+
+ for of_port in config["port_map"].keys():
+ logging.info("PacketInMiss test, port %d", of_port)
+ self.dataplane.send(of_port, pkt)
+
+ #AOS current packet in will not have vlan tag
+ if config["cicada_poject"]:
+ verify_packet_in(self, vlan_pkt, of_port, ofp.OFPR_ACTION)
+ else:
+ verify_packet_in(self, pkt, of_port, ofp.OFPR_ACTION)
+
+ verify_no_other_packets(self)
+
+class PacketOut(base_tests.SimpleDataPlane):
+ """
+ Verify action Flood, ALL, in port
+ """
+
+ def runTest(self):
+ if config["cicada_poject"]:
+ pass
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ parsed_pkt = simple_tcp_packet(pktlen=100)
+ parsed_vlan_pkt = simple_tcp_packet(pktlen=104,
+ vlan_vid=0x1002, dl_vlan_enable=True)
+
+ pkt = str(parsed_pkt)
+ vlan_pkt = str(parsed_vlan_pkt)
+
+
+ #packet out flood, untag packet
+ self.controller.message_send(ofp.message.packet_out(in_port=ofp.OFPP_CONTROLLER,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ actions=[ofp.action.output(
+ port=ofp.OFPP_FLOOD)],
+ data=pkt))
+
+ for of_port in config["port_map"].keys():
+ verify_packet(self, pkt, of_port)
+
+ verify_no_other_packets(self)
+
+ #packet out flood, tag packet, because it can't identify vlan has which port
+ #so we do as all action.
+ self.controller.message_send(ofp.message.packet_out(in_port=ofp.OFPP_CONTROLLER,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ actions=[ofp.action.output(
+ port=ofp.OFPP_FLOOD)],
+ data=vlan_pkt))
+
+ for of_port in config["port_map"].keys():
+ verify_packet(self, vlan_pkt, of_port)
+
+ verify_no_other_packets(self)
+
+ #packet out all
+ self.controller.message_send(ofp.message.packet_out(in_port=ofp.OFPP_CONTROLLER,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ actions=[ofp.action.output(
+ port=ofp.OFPP_FLOOD)],
+ data=pkt))
+
+ for of_port in config["port_map"].keys():
+ verify_packet(self, pkt, of_port)
+
+ verify_no_other_packets(self)
+
+ #packet out to in port
+ in_port = config["port_map"].keys()[0]
+ self.controller.message_send(ofp.message.packet_out(in_port=in_port,
+ buffer_id=ofp.OFP_NO_BUFFER,
+ actions=[ofp.action.output(
+ port=in_port)],
+ data=pkt))
+
+ verify_packet(self, pkt, in_port)
+ verify_no_other_packets(self)
+
+class L3UcastRoute(base_tests.SimpleDataPlane):
+ """
+ Port1(vlan1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port2(vlan2, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ if len(config["port_map"]) <2:
+ logging.info("Port count less than 2, can't run this case")
+ return
+
+ vlan_id=1
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ dst_mac=[0x00, 0x00, 0x00, 0x22, 0x22, 0x00]
+ dip=0xc0a80001
+ for port in config["port_map"].keys():
+ #add l2 interface group
+ add_one_l2_interface_group(self.controller, port, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ dst_mac[5]=vlan_id
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vlan_id, id=vlan_id, src_mac=intf_src_mac, dst_mac=dst_mac)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vlan_id, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ #add termination flow
+ add_termination_flow(self.controller, port, 0x0800, intf_src_mac, vlan_id)
+ #add unicast routing flow
+ dst_ip = dip + (vlan_id<<8)
+ add_unicast_routing_flow(self.controller, 0x0800, dst_ip, 0, l3_msg.group_id)
+ vlan_id += 1
+
+ do_barrier(self.controller)
+
+ port1=config["port_map"].keys()[0]
+ port2=config["port_map"].keys()[1]
+ #port 1 to port 2
+ switch_mac = ':'.join(['%02X' % x for x in intf_src_mac])
+ dst_mac[5]=1
+ port1_mac=':'.join(['%02X' % x for x in dst_mac])
+
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac,
+ eth_src=port1_mac,
+ ip_ttl=64,
+ ip_src="192.168.1.1",
+ ip_dst='192.168.2.1')
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port1, pkt)
+ #build expect packet
+ dst_mac[5]=2
+ port2_mac=':'.join(['%02X' % x for x in dst_mac])
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port2_mac,
+ eth_src=switch_mac,
+ ip_ttl=63,
+ ip_src="192.168.1.1",
+ ip_dst='192.168.2.1')
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port2)
+ verify_no_other_packets(self)
+
+ #port 2 to port 1
+ switch_mac = ':'.join(['%02X' % x for x in intf_src_mac])
+ dst_mac[5]=2
+ port2_mac=':'.join(['%02X' % x for x in dst_mac])
+
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac,
+ eth_src=port2_mac,
+ ip_ttl=64,
+ ip_src="192.168.2.1",
+ ip_dst='192.168.1.1')
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port2, pkt)
+ #build expect packet
+ dst_mac[5]=1
+ port1_mac=':'.join(['%02X' % x for x in dst_mac])
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port1_mac,
+ eth_src=switch_mac,
+ ip_ttl=63,
+ ip_src="192.168.2.1",
+ ip_dst='192.168.1.1')
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port1)
+ verify_no_other_packets(self)
+
+class L3UcastRouteOnSamVLANSamPort(base_tests.SimpleDataPlane):
+ """
+ Port1(vlan1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port1(vlan1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ port = config["port_map"].keys()[0]
+
+ vlan_id=1
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ port_mac1=[0x00, 0x00, 0x00, 0x22, 0x22, 0x01]
+ port_mac2=[0x00, 0x00, 0x00, 0x22, 0x22, 0x02]
+ port_ip1=0xc0a80101
+ port_ip1_str=convertIP4toStr(port_ip1)
+ port_ip2=0xc0a80201
+ port_ip2_str=convertIP4toStr(port_ip2)
+ #add l2 interface group
+ add_one_l2_interface_group(self.controller, port, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vlan_id, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ #add termination flow
+ add_termination_flow(self.controller, port, 0x0800, intf_src_mac, vlan_id)
+
+ """192.168.1.1->192.168.2.1"""
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vlan_id, id=1, src_mac=intf_src_mac, dst_mac=port_mac2)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip2, 0, l3_msg.group_id)
+ """192.168.1.1->192.168.2.1"""
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vlan_id, id=2, src_mac=intf_src_mac, dst_mac=port_mac1)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip1, 0, l3_msg.group_id)
+
+ do_barrier(self.controller)
+
+ """send packet to verify"""
+ """192.168.1.1->192.168.2.1"""
+ switch_mac_str = convertMACtoStr(intf_src_mac)
+ port_mac1_str = convertMACtoStr(port_mac1)
+ port_mac2_str = convertMACtoStr(port_mac2)
+ ttl=64
+ #send packet
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac1_str,
+ ip_ttl=ttl,
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac2_str,
+ eth_src=switch_mac_str,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+ """192.168.2.1->192.168.1.1"""
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac2_str,
+ ip_ttl=ttl,
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac1_str,
+ eth_src=switch_mac_str,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+class L3UcastRouteOnDiffVLANSamPort(base_tests.SimpleDataPlane):
+ """
+ Port1(vlan1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port1(vlan2, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ port = config["port_map"].keys()[0]
+
+ port_vlan_id1=1
+ port_vlan_id2=2
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ port_mac1=[0x00, 0x00, 0x00, 0x22, 0x22, 0x01]
+ port_mac2=[0x00, 0x00, 0x00, 0x22, 0x22, 0x02]
+ port_ip1=0xc0a80101
+ port_ip1_str=convertIP4toStr(port_ip1)
+ port_ip2=0xc0a80201
+ port_ip2_str=convertIP4toStr(port_ip2)
+ #add l2 interface group
+ add_one_l2_interface_group(self.controller, port, vlan_id=port_vlan_id1, is_tagged=True, send_barrier=False)
+ add_one_l2_interface_group(self.controller, port, vlan_id=port_vlan_id2, is_tagged=True, send_barrier=False)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, port_vlan_id1, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ add_one_vlan_table_flow(self.controller, port, port_vlan_id2, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ #add termination flow
+ add_termination_flow(self.controller, port, 0x0800, intf_src_mac, port_vlan_id1)
+ add_termination_flow(self.controller, port, 0x0800, intf_src_mac, port_vlan_id2)
+
+ """192.168.1.1->192.168.2.1"""
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=port_vlan_id2, id=1, src_mac=intf_src_mac, dst_mac=port_mac2)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip2, 0, l3_msg.group_id)
+ """192.168.1.1->192.168.2.1"""
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=port_vlan_id1, id=2, src_mac=intf_src_mac, dst_mac=port_mac1)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip1, 0, l3_msg.group_id)
+
+ do_barrier(self.controller)
+
+ """send packet to verify"""
+ """192.168.1.1->192.168.2.1"""
+ switch_mac_str =convertMACtoStr(intf_src_mac)
+ port_mac1_str= convertMACtoStr(port_mac1)
+ port_mac2_str= convertMACtoStr(port_mac2)
+ ttl=64
+ #send packet
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac1_str,
+ dl_vlan_enable=True,
+ vlan_vid=port_vlan_id1,
+ ip_ttl=ttl,
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac2_str,
+ eth_src=switch_mac_str,
+ dl_vlan_enable=True,
+ vlan_vid=port_vlan_id2,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+ """192.168.2.1->192.168.1.1"""
+ switch_mac = convertMACtoStr(intf_src_mac)
+ port_mac2_str=convertMACtoStr(port_mac2)
+
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac2_str,
+ dl_vlan_enable=True,
+ vlan_vid=port_vlan_id2,
+ ip_ttl=ttl,
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac1_str,
+ eth_src=switch_mac_str,
+ dl_vlan_enable=True,
+ vlan_vid=port_vlan_id1,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+class L3UcastVrfRouteOnSamVLANSamPort(base_tests.SimpleDataPlane):
+ """
+ Port1(vlan1, VRF1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port1(vlan1, VRF1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+ Port1(vlan2, VRF2, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port1(vlan2, VRF2, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ port = config["port_map"].keys()[0]
+
+ vrf1=1
+ vrf2=2
+ vrf1_vlan_id=1
+ vrf2_vlan_id=2
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ port_mac1=[0x00, 0x00, 0x00, 0x22, 0x22, 0x01]
+ port_mac2=[0x00, 0x00, 0x00, 0x22, 0x22, 0x02]
+ port_ip1=0xc0a80101
+ port_ip1_str=convertIP4toStr(port_ip1)
+ port_ip2=0xc0a80201
+ port_ip2_str=convertIP4toStr(port_ip2)
+ #add l2 interface group
+ add_one_l2_interface_group(self.controller, port, vlan_id=vrf1_vlan_id, is_tagged=True, send_barrier=False)
+ add_one_l2_interface_group(self.controller, port, vlan_id=vrf2_vlan_id, is_tagged=True, send_barrier=False)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vrf1_vlan_id, vrf=vrf1, flag=VLAN_TABLE_FLAG_ONLY_TAG)
+ add_one_vlan_table_flow(self.controller, port, vrf2_vlan_id, vrf=vrf2, flag=VLAN_TABLE_FLAG_ONLY_TAG)
+
+ #add termination flow
+ add_termination_flow(self.controller, 0, 0x0800, intf_src_mac, vrf1_vlan_id)
+ add_termination_flow(self.controller, 0, 0x0800, intf_src_mac, vrf2_vlan_id)
+
+ """192.168.1.1->192.168.2.1"""
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vrf1_vlan_id, id=1, src_mac=intf_src_mac, dst_mac=port_mac2)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip2, 0, l3_msg.group_id, vrf1)
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vrf2_vlan_id, id=2, src_mac=intf_src_mac, dst_mac=port_mac2)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip2, 0, l3_msg.group_id, vrf2)
+
+ """192.168.1.1->192.168.2.1"""
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vrf1_vlan_id, id=3, src_mac=intf_src_mac, dst_mac=port_mac1)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip1, 0, l3_msg.group_id, vrf1)
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vrf2_vlan_id, id=4, src_mac=intf_src_mac, dst_mac=port_mac1)
+ add_unicast_routing_flow(self.controller, 0x0800, port_ip1, 0, l3_msg.group_id, vrf2)
+
+ do_barrier(self.controller)
+
+ """send packet to verify on VRF vrf1"""
+ """192.168.1.1->192.168.2.1"""
+ switch_mac_str = convertMACtoStr(intf_src_mac)
+ port_mac1_str = convertMACtoStr(port_mac1)
+ port_mac2_str = convertMACtoStr(port_mac2)
+ ttl=64
+ #send packet
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac1_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf1_vlan_id,
+ ip_ttl=ttl,
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac2_str,
+ eth_src=switch_mac_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf1_vlan_id,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+ """192.168.2.1->192.168.1.1"""
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac2_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf1_vlan_id,
+ ip_ttl=ttl,
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac1_str,
+ eth_src=switch_mac_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf1_vlan_id,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+
+ """send packet to verify on VRF vrf2"""
+ """192.168.1.1->192.168.2.1"""
+ switch_mac_str = convertMACtoStr(intf_src_mac)
+ port_mac1_str = convertMACtoStr(port_mac1)
+ port_mac2_str = convertMACtoStr(port_mac2)
+ ttl=64
+ #send packet
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac1_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf2_vlan_id,
+ ip_ttl=ttl,
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac2_str,
+ eth_src=switch_mac_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf2_vlan_id,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip1_str,
+ ip_dst=port_ip2_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+ """192.168.2.1->192.168.1.1"""
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac_str,
+ eth_src=port_mac2_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf2_vlan_id,
+ ip_ttl=ttl,
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port, pkt)
+ #build expect packet
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port_mac1_str,
+ eth_src=switch_mac_str,
+ dl_vlan_enable=True,
+ vlan_vid=vrf2_vlan_id,
+ ip_ttl=(ttl-1),
+ ip_src=port_ip2_str,
+ ip_dst=port_ip1_str)
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port)
+ verify_no_other_packets(self)
+
+
+
+
+class L3UcastECMP(base_tests.SimpleDataPlane):
+ """
+ Port1(vlan1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port2(vlan2, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ if len(config["port_map"]) <2:
+ logging.info("Port count less than 2, can't run this case")
+ return
+
+ vlan_id=1
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ dst_mac=[0x00, 0x00, 0x00, 0x22, 0x22, 0x00]
+ dip=0xc0a80001
+ for port in config["port_map"].keys():
+ #add l2 interface group
+ add_one_l2_interface_group(self.controller, port, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ dst_mac[5]=vlan_id
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vlan_id, id=vlan_id, src_mac=intf_src_mac, dst_mac=dst_mac)
+ ecmp_msg=add_l3_ecmp_group(self.controller, vlan_id, [l3_msg.group_id])
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vlan_id, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ #add termination flow
+ add_termination_flow(self.controller, port, 0x0800, intf_src_mac, vlan_id)
+ #add unicast routing flow
+ dst_ip = dip + (vlan_id<<8)
+ #ECMP shall have prefix not 32
+ add_unicast_routing_flow(self.controller, 0x0800, dst_ip, 0xffffff00, ecmp_msg.group_id)
+ vlan_id += 1
+
+ do_barrier(self.controller)
+
+ port1=config["port_map"].keys()[0]
+ port2=config["port_map"].keys()[1]
+ #port 1 to port 2
+ switch_mac = ':'.join(['%02X' % x for x in intf_src_mac])
+ dst_mac[5]=1
+ port1_mac=':'.join(['%02X' % x for x in dst_mac])
+
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac,
+ eth_src=port1_mac,
+ ip_ttl=64,
+ ip_src="192.168.1.1",
+ ip_dst='192.168.2.1')
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port1, pkt)
+ #build expect packet
+ dst_mac[5]=2
+ port2_mac=':'.join(['%02X' % x for x in dst_mac])
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port2_mac,
+ eth_src=switch_mac,
+ ip_ttl=63,
+ ip_src="192.168.1.1",
+ ip_dst='192.168.2.1')
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port2)
+ verify_no_other_packets(self)
+
+ #port 2 to port 1
+ switch_mac = ':'.join(['%02X' % x for x in intf_src_mac])
+ dst_mac[5]=2
+ port2_mac=':'.join(['%02X' % x for x in dst_mac])
+
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac,
+ eth_src=port2_mac,
+ ip_ttl=64,
+ ip_src="192.168.2.1",
+ ip_dst='192.168.1.1')
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port2, pkt)
+ #build expect packet
+ dst_mac[5]=1
+ port1_mac=':'.join(['%02X' % x for x in dst_mac])
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=port1_mac,
+ eth_src=switch_mac,
+ ip_ttl=63,
+ ip_src="192.168.2.1",
+ ip_dst='192.168.1.1')
+ pkt=str(exp_pkt)
+ verify_packet(self, pkt, port1)
+ verify_no_other_packets(self)
+
+
+class L3UcastECMP2(base_tests.SimpleDataPlane):
+ """
+ Port1(vlan1, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 192.168.1.1) ,
+ Port2(vlan2, 0x00, 0x00, 0x00, 0x22, 0x22, 0x02, 19.168.2.1)
+ Portn(vlann, 0x00, 0x00, 0x00, 0x22, 0x22, 0x0n, 19.168.n.1)
+ """
+
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ if len(config["port_map"]) <3:
+ logging.info("Port count less than 3, can't run this case")
+ return
+
+ vlan_id=1
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ same_dst_mac=[0x00, 0x00, 0x00, 0x22, 0x22, 0x22]
+
+ l3_ucast_gips=[]
+ tx_port = config["port_map"].keys()[0]
+ for port in config["port_map"].keys():
+ #add l2 interface group
+ add_one_l2_interface_group(self.controller, port, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ if tx_port != port:
+ l3_msg=add_l3_unicast_group(self.controller, port, vlanid=vlan_id, id=vlan_id, src_mac=intf_src_mac, dst_mac=same_dst_mac)
+ l3_ucast_gips.append(l3_msg.group_id)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vlan_id, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ #add termination flow
+ add_termination_flow(self.controller, port, 0x0800, intf_src_mac, vlan_id)
+ vlan_id += 1
+
+ tx_dip=0x0a0a0a0a
+ tx_sip=0x0b0a0a0a
+ ecmp_msg=add_l3_ecmp_group(self.controller, vlan_id, l3_ucast_gips)
+ #ECMP shall have prefix not 32
+ add_unicast_routing_flow(self.controller, 0x0800, tx_dip, 0xffffff00, ecmp_msg.group_id)
+
+ do_barrier(self.controller)
+
+ switch_mac = ':'.join(['%02X' % x for x in intf_src_mac])
+ packet_src_mac="00:00:33:44:55:66"
+ #from unknown src ip to unknown dst ip, to verify ecmp
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac,
+ eth_src=packet_src_mac,
+ ip_ttl=64,
+ ip_src=convertIP4toStr(tx_sip),
+ ip_dst=convertIP4toStr(tx_dip))
+ self.dataplane.send(tx_port, str(parsed_pkt))
+ #build expect packet
+ dst_mac=':'.join(['%02X' % x for x in same_dst_mac])
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=dst_mac,
+ eth_src=switch_mac,
+ ip_ttl=63,
+ ip_src=convertIP4toStr(tx_sip),
+ ip_dst=convertIP4toStr(tx_dip))
+
+ verify_packet(self, exp_pkt, config["port_map"].keys()[2])
+ verify_no_other_packets(self)
+ tx_sip=tx_sip+0x01000000
+ #from unknown scr ip to unknown dst ip, to verify ecmp
+ parsed_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=switch_mac,
+ eth_src=packet_src_mac,
+ ip_ttl=64,
+ ip_src=convertIP4toStr(tx_sip),
+ ip_dst=convertIP4toStr(tx_dip))
+ self.dataplane.send(tx_port, str(parsed_pkt))
+ #build expect packet
+ dst_mac=':'.join(['%02X' % x for x in same_dst_mac])
+ exp_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst=dst_mac,
+ eth_src=switch_mac,
+ ip_ttl=63,
+ ip_src=convertIP4toStr(tx_sip),
+ ip_dst=convertIP4toStr(tx_dip))
+
+ verify_packet(self, exp_pkt, config["port_map"].keys()[1])
+ verify_no_other_packets(self)
+
+class L3McastRoute1(base_tests.SimpleDataPlane):
+ """
+ Mcast routing, From VLAN 1 to VLAN 2
+ """
+ def runTest(self):
+ """
+ port1 (vlan 1)-> port 2 (vlan 2)
+ """
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ if len(config["port_map"]) <3:
+ logging.info("Port count less than 2, can't run this case")
+ return
+
+ vlan_id =1
+ port2_out_vlan=2
+ port3_out_vlan=3
+ in_vlan=1 #macast group vid shall use input vlan diffe from l3 interface use output vlan
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ intf_src_mac_str=':'.join(['%02X' % x for x in intf_src_mac])
+ dst_mac=[0x01, 0x00, 0x5e, 0x01, 0x01, 0x01]
+ dst_mac_str=':'.join(['%02X' % x for x in dst_mac])
+ port1_mac=[0x00, 0x11, 0x11, 0x11, 0x11, 0x11]
+ port1_mac_str=':'.join(['%02X' % x for x in port1_mac])
+ src_ip=0xc0a80101
+ src_ip_str="192.168.1.1"
+ dst_ip=0xe0010101
+ dst_ip_str="224.1.1.1"
+
+ port1=config["port_map"].keys()[0]
+ port2=config["port_map"].keys()[1]
+ port3=config["port_map"].keys()[2]
+
+ #add l2 interface group
+ for port in config["port_map"].keys():
+ add_one_l2_interface_group(self.controller, port, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vlan_id, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+ vlan_id +=1
+
+ #add termination flow
+ add_termination_flow(self.controller, port1, 0x0800, [0x01, 0x00, 0x5e, 0x00, 0x00, 0x00], vlan_id)
+
+ #add l3 interface group
+ port2_ucast_msg=add_l3_interface_group(self.controller, port2, port2_out_vlan, 2, intf_src_mac)
+ port3_ucast_msg=add_l3_interface_group(self.controller, port3, port3_out_vlan, 3, intf_src_mac)
+ mcat_group_msg=add_l3_mcast_group(self.controller, in_vlan, 2, [port2_ucast_msg.group_id, port3_ucast_msg.group_id])
+ add_mcast4_routing_flow(self.controller, in_vlan, src_ip, 0, dst_ip, mcat_group_msg.group_id)
+
+ parsed_pkt = simple_udp_packet(pktlen=100,
+ eth_dst=dst_mac_str,
+ eth_src=port1_mac_str,
+ ip_ttl=64,
+ ip_src=src_ip_str,
+ ip_dst=dst_ip_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port1, pkt)
+ parsed_pkt = simple_udp_packet(pktlen=100,
+ eth_dst=dst_mac_str,
+ eth_src=intf_src_mac_str,
+ ip_ttl=63,
+ ip_src=src_ip_str,
+ ip_dst=dst_ip_str)
+ pkt=str(parsed_pkt)
+ verify_packet(self, pkt, port2)
+ verify_packet(self, pkt, port3)
+ verify_no_other_packets(self)
+
+class L3McastRoute2(base_tests.SimpleDataPlane):
+ """
+ Mcast routing, but on same vlan (l2mcast)
+ """
+ def runTest(self):
+ """
+ port1 (vlan 1)-> port 2 (vlan 1)
+ """
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ if len(config["port_map"]) <2:
+ logging.info("Port count less than 2, can't run this case")
+ return
+
+ vlan_id =1
+ intf_src_mac=[0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc]
+ intf_src_mac_str=':'.join(['%02X' % x for x in intf_src_mac])
+ dst_mac=[0x01, 0x00, 0x5e, 0x01, 0x01, 0x01]
+ dst_mac_str=':'.join(['%02X' % x for x in dst_mac])
+ port1_mac=[0x00, 0x11, 0x11, 0x11, 0x11, 0x11]
+ port1_mac_str=':'.join(['%02X' % x for x in port1_mac])
+ src_ip=0xc0a80101
+ src_ip_str="192.168.1.1"
+ dst_ip=0xe0010101
+ dst_ip_str="224.1.1.1"
+
+ port1=config["port_map"].keys()[0]
+ port2=config["port_map"].keys()[1]
+
+
+ #add l2 interface group
+ l2_intf_group_list=[]
+ for port in config["port_map"].keys():
+ if port != port1 and port !=port2:
+ continue
+ l2_intf_gid, msg=add_one_l2_interface_group(self.controller, port, vlan_id=vlan_id, is_tagged=False, send_barrier=False)
+ l2_intf_group_list.append(l2_intf_gid)
+ #add vlan flow table
+ add_one_vlan_table_flow(self.controller, port, vlan_id, flag=VLAN_TABLE_FLAG_ONLY_BOTH)
+
+ #add termination flow
+ add_termination_flow(self.controller, port1, 0x0800, [0x01, 0x00, 0x5e, 0x00, 0x00, 0x00], vlan_id)
+
+ #add l3 interface group
+ mcat_group_msg=add_l3_mcast_group(self.controller, vlan_id, 2, l2_intf_group_list)
+ add_mcast4_routing_flow(self.controller, vlan_id, src_ip, 0, dst_ip, mcat_group_msg.group_id)
+
+ parsed_pkt = simple_udp_packet(pktlen=100,
+ eth_dst=dst_mac_str,
+ eth_src=port1_mac_str,
+ ip_ttl=64,
+ ip_src=src_ip_str,
+ ip_dst=dst_ip_str)
+ pkt=str(parsed_pkt)
+ self.dataplane.send(port1, pkt)
+ verify_packet(self, pkt, port2)
+ verify_no_other_packets(self)
+
+
+
diff --git a/Fabric/Utilities/accton/flow_test2.py b/Fabric/Utilities/accton/flow_test2.py
new file mode 100755
index 0000000..cfe1296
--- /dev/null
+++ b/Fabric/Utilities/accton/flow_test2.py
@@ -0,0 +1,74 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+Flow Test
+
+Test each flow table can set entry, and packet rx correctly.
+"""
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+from oftest.testutils import *
+from accton_util import *
+
+class qinq(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ in_port = config["port_map"].keys()[0]
+ out_port=config["port_map"].keys()[1]
+ out_vlan=10
+ add_vlan_table_flow_pvid(self.controller, in_port, None, out_vlan, False)
+ add_vlan_table_flow_pvid(self.controller, in_port, 1,out_vlan, False)
+ group_id, msg=add_one_l2_interface_group(self.controller, out_port, out_vlan, True, False)
+ #add acl
+ match = ofp.match()
+ match.oxm_list.append(ofp.oxm.in_port(in_port))
+ request = ofp.message.flow_add(
+ table_id=60,
+ cookie=42,
+ match=match,
+ instructions=[
+ ofp.instruction.write_actions(
+ actions=[
+ ofp.action.group(msg.group_id)])
+ ],
+ buffer_id=ofp.OFP_NO_BUFFER,
+ priority=1000)
+ self.controller.message_send(request)
+
+ #input untag packet
+
+ parsed_pkt = simple_tcp_packet(pktlen=100)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(in_port, pkt)
+
+ parsed_pkt = simple_tcp_packet(pktlen=104, dl_vlan_enable=True, vlan_vid=10)
+ verify_packet(self, str(parsed_pkt), out_port)
+
+ #input tag packet
+ parsed_pkt = simple_tcp_packet(pktlen=104, dl_vlan_enable=True, vlan_vid=1)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(in_port, pkt)
+
+ parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True, out_vlan_vid=10,
+ in_dl_vlan_enable=True, in_vlan_vid=1)
+ verify_packet(self, str(parsed_pkt), out_port)
diff --git a/Fabric/Utilities/accton/group_test.py b/Fabric/Utilities/accton/group_test.py
new file mode 100755
index 0000000..67d6fda
--- /dev/null
+++ b/Fabric/Utilities/accton/group_test.py
@@ -0,0 +1,883 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+Group table test
+Verify each group table can created correctly
+"""
+from oftest import config
+
+import logging
+import random
+
+from oftest import config
+import oftest
+import oftest.base_tests as base_tests
+import ofp
+
+from oftest.testutils import *
+from accton_util import *
+
+def getkey(type):
+ def byGroupId(stats_entry):
+ return stats_entry.group_id
+
+ def byGroupType(stats_entry):
+ return stats_entry.group_type
+
+
+ if type == "group_id":
+ return byGroupId
+ elif type == "group_type":
+ return byGroupType
+ else:
+ assert(0)
+ return byGroupId
+
+class L2InterfaceGroupOne(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_one_l2_interface_group(self.controller, config["port_map"].keys()[0], 1, False, False)
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[ofp.group_desc_stats_entry(
+ group_type=msg1.group_type,
+ group_id=msg1.group_id,
+ buckets=msg1.buckets)]
+
+ self.maxDiff=None
+
+ self.assertEquals(stats, verify_group_stats)
+
+class L2InterfaceGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ group_list2, msg2 =add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets))
+
+ for msg in msg2:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets))
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ #self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+class L2McastGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ msg2=add_l2_mcast_group(self.controller, config["port_map"].keys(), 1, 1)
+
+ group_list1, msg3 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+ msg4=add_l2_mcast_group(self.controller, config["port_map"].keys(), 2, 2)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class L2FloodGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ msg2=add_l2_flood_group(self.controller, config["port_map"].keys(), 1, 1)
+
+ group_list1, msg3 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+ msg4=add_l2_flood_group(self.controller, config["port_map"].keys(), 2, 2)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class L2RewriteGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ msg2=add_l2_rewrite_group(self.controller, config["port_map"].keys()[0], 1, 1, [00,11,22,33,44,55], [00,22,22,22,22,22])
+
+ group_list1, msg3 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+ msg4=add_l2_rewrite_group(self.controller, config["port_map"].keys()[0], 2, 2, [00,11,22,33,44,55], [00,33,33,33,33,33])
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class L3UnicastGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ msg2=add_l3_unicast_group(self.controller, config["port_map"].keys()[0], 1, 1, [0x00,0x11,0x22,0x33,0x44,0x55], [00,0x22,0x22,0x22,0x22,0x22])
+
+ group_list1, msg3 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+ msg4=add_l3_unicast_group(self.controller, config["port_map"].keys()[0], 2, 2, [0x00,0x11,0x22,0x33,0x44,0x55], [00,0x33,0x33,0x33,0x33,0x33])
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class L3ECMPGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ msg2=add_l3_unicast_group(self.controller, config["port_map"].keys()[0], 1, 1, [0x00,0x11,0x22,0x33,0x44,0x55], [00,0x22,0x22,0x22,0x22,0x22])
+
+ group_list1, msg3 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+ msg4=add_l3_unicast_group(self.controller, config["port_map"].keys()[0], 2, 2, [0x00,0x11,0x22,0x33,0x44,0x55], [00,0x33,0x33,0x33,0x33,0x33])
+
+ group_ids=[msg2.group_id, msg4.group_id]
+
+ msg5=add_l3_ecmp_group(self.controller, 1, group_ids)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg5.group_type,
+ group_id=msg5.group_id,
+ buckets=msg5.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class L3InterfaceGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ group_list1, msg1 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 1, False, False)
+ msg2=add_l3_interface_group(self.controller, config["port_map"].keys()[0], 1, 1, [0x00,0x11,0x22,0x33,0x44,0x55])
+ group_list1, msg3 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 2, False, False)
+ msg4=add_l3_interface_group(self.controller, config["port_map"].keys()[0], 2, 2, [0x00,0x11,0x22,0x33,0x44,0x66])
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class L3McastGroup(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ # Vlan 3 forward to vlan 3 port 1 and 2
+ # Vlan 3 foward to vlan 1 port 1
+ # Vlan 3 foward to vlan 2 port 1
+ # Vlan 3 foward to vlan 2 port 2
+ group_list1_1, msg1 = add_l2_interface_grouop(self.controller, [config["port_map"].keys()[0]], 1, False, False)
+ msg2=add_l3_interface_group(self.controller, config["port_map"].keys()[0], 1, 1, [0x00,0x11,0x22,0x33,0x44,0x11])
+ group_list1_2, msg3 = add_l2_interface_grouop(self.controller, [config["port_map"].keys()[0]], 2, False, False)
+ msg4=add_l3_interface_group(self.controller, config["port_map"].keys()[0], 2, 2, [0x00,0x11,0x22,0x33,0x44,0x22])
+ group_list2_1, msg5 = add_l2_interface_grouop(self.controller, [config["port_map"].keys()[1]], 2, False, False)
+ msg6=add_l3_interface_group(self.controller, config["port_map"].keys()[1], 2, 3, [0x00,0x11,0x22,0x33,0x44,0x33])
+ group_list3, msg7 = add_l2_interface_grouop(self.controller, config["port_map"].keys(), 3, False, False)
+
+ group_actions=[msg2.group_id, msg4.group_id, msg6.group_id]
+ group_actions.extend(group_list3)
+
+ msg8=add_l3_mcast_group(self.controller, 3, 1, group_actions)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in msg1:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg2.group_type,
+ group_id=msg2.group_id,
+ buckets=msg2.buckets)
+ )
+
+ for msg in msg3:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg4.group_type,
+ group_id=msg4.group_id,
+ buckets=msg4.buckets)
+ )
+ for msg in msg5:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg6.group_type,
+ group_id=msg6.group_id,
+ buckets=msg6.buckets)
+ )
+ for msg in msg7:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg8.group_type,
+ group_id=msg8.group_id,
+ buckets=msg8.buckets)
+ )
+
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+
+ self.maxDiff=None
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_intf_group(base_tests.SimpleDataPlane):
+ """
+ create mpls intf group
+ 1. ref l2_intf_group
+ 2. ref l2_flood_group
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, config["port_map"].keys()[0], test_vid, False, False)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=1)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_intf_msg.group_type,
+ group_id=mpls_intf_msg.group_id,
+ buckets=mpls_intf_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_l2_vpn_group(base_tests.SimpleDataPlane):
+ """
+ create mpls intf group
+ 1. ref l2_intf_group
+
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ test_port=config["port_map"].keys()[0]
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, test_port, test_vid, False, False)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=1)
+ mpls_label_gid, mpls_label_msg=add_mpls_label_group(self.controller, subtype=OFDPA_MPLS_GROUP_SUBTYPE_L2_VPN_LABEL,
+ index=1,
+ ref_gid=mpls_intf_gid,
+ push_l2_header=True,
+ push_vlan=True,
+ push_mpls_header=True,
+ push_cw=False,
+ set_mpls_label=10,
+ set_bos=0,
+ set_tc=7,
+ set_tc_from_table=False,
+ cpy_tc_outward=False,
+ set_ttl=250,
+ cpy_ttl_outward=False,
+ oam_lm_tx_count=False,
+ set_pri_from_table=False
+ )
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_intf_msg.group_type,
+ group_id=mpls_intf_msg.group_id,
+ buckets=mpls_intf_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_label_msg.group_type,
+ group_id=mpls_label_msg.group_id,
+ buckets=mpls_label_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats= get_stats(self, ofp.message.group_desc_stats_request())
+ stats=sorted(stats, key=getkey("group_id"))
+ #DumpGroup(stats, verify_group_stats)
+ #AssertGroup(self, stats, verify_group_stats)
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_tunnel_lable1_group(base_tests.SimpleDataPlane):
+ """
+ create mpls intf group
+ 1. ref l2_intf_group
+
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ test_port=config["port_map"].keys()[0]
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, test_port, test_vid, False, False)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=1)
+ mpls_label_gid, mpls_label_msg=add_mpls_label_group(self.controller, subtype=OFDPA_MPLS_GROUP_SUBTYPE_TUNNEL_LABEL1,
+ index=1,
+ ref_gid=mpls_intf_gid,
+ push_l2_header=True,
+ push_vlan=True,
+ push_mpls_header=True,
+ push_cw=True,
+ set_mpls_label=10,
+ set_bos=0,
+ set_tc=7,
+ set_tc_from_table=False,
+ cpy_tc_outward=False,
+ set_ttl=250,
+ cpy_ttl_outward=False,
+ oam_lm_tx_count=False,
+ set_pri_from_table=False
+ )
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_intf_msg.group_type,
+ group_id=mpls_intf_msg.group_id,
+ buckets=mpls_intf_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_label_msg.group_type,
+ group_id=mpls_label_msg.group_id,
+ buckets=mpls_label_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_tunnel_lable2_group(base_tests.SimpleDataPlane):
+ """
+ create mpls intf group
+ 1. ref l2_intf_group
+
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ test_port=config["port_map"].keys()[0]
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, test_port, test_vid, False, False)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=1)
+ mpls_label_gid, mpls_label_msg=add_mpls_label_group(self.controller, subtype=OFDPA_MPLS_GROUP_SUBTYPE_TUNNEL_LABEL2,
+ index=1,
+ ref_gid=mpls_intf_gid,
+ push_l2_header=True,
+ push_vlan=True,
+ push_mpls_header=True,
+ push_cw=True,
+ set_mpls_label=10,
+ set_bos=0,
+ set_tc=7,
+ set_tc_from_table=False,
+ cpy_tc_outward=False,
+ set_ttl=250,
+ cpy_ttl_outward=False,
+ oam_lm_tx_count=False,
+ set_pri_from_table=False
+ )
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_intf_msg.group_type,
+ group_id=mpls_intf_msg.group_id,
+ buckets=mpls_intf_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_label_msg.group_type,
+ group_id=mpls_label_msg.group_id,
+ buckets=mpls_label_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.assertEquals(stats, verify_group_stats)
+
+class mpls_swap_label_group(base_tests.SimpleDataPlane):
+ """
+ create mpls intf group
+ 1. ref l2_intf_group
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ test_port=config["port_map"].keys()[0]
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, test_port, test_vid, False, False)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=1)
+ mpls_label_gid, mpls_label_msg=add_mpls_label_group(self.controller, subtype=OFDPA_MPLS_GROUP_SUBTYPE_SWAP_LABEL,
+ index=1,
+ ref_gid=mpls_intf_gid,
+ push_l2_header=True,
+ push_vlan=True,
+ push_mpls_header=True,
+ push_cw=True,
+ set_mpls_label=10,
+ set_bos=0,
+ set_tc=7,
+ set_tc_from_table=False,
+ cpy_tc_outward=False,
+ set_ttl=250,
+ cpy_ttl_outward=False,
+ oam_lm_tx_count=False,
+ set_pri_from_table=False
+ )
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_intf_msg.group_type,
+ group_id=mpls_intf_msg.group_id,
+ buckets=mpls_intf_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_label_msg.group_type,
+ group_id=mpls_label_msg.group_id,
+ buckets=mpls_label_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_forwarding_group_fastfailover(base_tests.SimpleDataPlane):
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ test_port=config["port_map"].keys()[0]
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, test_port, test_vid, False, False)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=1)
+ mpls_label_gid, mpls_label_msg=add_mpls_label_group(self.controller, subtype=OFDPA_MPLS_GROUP_SUBTYPE_SWAP_LABEL,
+ index=1,
+ ref_gid=mpls_intf_gid,
+ push_l2_header=True,
+ push_vlan=True,
+ push_mpls_header=True,
+ push_cw=True,
+ set_mpls_label=10,
+ set_bos=0,
+ set_tc=7,
+ set_tc_from_table=False,
+ cpy_tc_outward=False,
+ set_ttl=250,
+ cpy_ttl_outward=False,
+ oam_lm_tx_count=False,
+ set_pri_from_table=False
+ )
+ mpls_fwd_gid, mpls_fwd_msg=add_mpls_forwarding_group(self.controller,
+ subtype=OFDPA_MPLS_GROUP_SUBTYPE_FAST_FAILOVER_GROUP,
+ index=1,
+ ref_gids=[mpls_label_gid],
+ watch_port=test_port,
+ watch_group=ofp.OFPP_ANY,
+ push_vlan=None,
+ pop_vlan=None,
+ set_vid=None)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_intf_msg.group_type,
+ group_id=mpls_intf_msg.group_id,
+ buckets=mpls_intf_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_label_msg.group_type,
+ group_id=mpls_label_msg.group_id,
+ buckets=mpls_label_msg.buckets)
+ )
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_fwd_msg.group_type,
+ group_id=mpls_fwd_msg.group_id,
+ buckets=mpls_fwd_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_forwarding_group_ecmp(base_tests.SimpleDataPlane):
+ """chip not support to bind flow on trident2
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ mpls_intf_msgs=[]
+ mpls_intf_gids=[]
+ l2_intf_msgs=[]
+ index=1
+ #ref l2_intf_group
+ for port in config["port_map"].keys():
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, port, test_vid, False, False)
+ l2_intf_msgs.append(l2_intf_msg)
+ mpls_intf_gid, mpls_intf_msg=add_mpls_intf_group(self.controller, l2_intf_gid, [0x00,0x11,0x11,0x11,0x11,0x11], [0x00,0x22,0x22,0x22,0x22,0x22], vid=test_vid, index=index)
+ index=index+1
+ mpls_intf_msgs.append(mpls_intf_msg)
+ mpls_intf_gids.append(mpls_intf_gid)
+
+ mpls_fwd_gid, mpls_fwd_msg=add_mpls_forwarding_group(self.controller,
+ subtype=OFDPA_MPLS_GROUP_SUBTYPE_ECMP,
+ index=1,
+ ref_gids=mpls_intf_gids,
+ watch_port=None,
+ watch_group=None,
+ push_vlan=None,
+ pop_vlan=None,
+ set_vid=None)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ for msg in l2_intf_msgs:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ for msg in mpls_intf_msgs:
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_fwd_msg.group_type,
+ group_id=mpls_fwd_msg.group_id,
+ buckets=mpls_fwd_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+ self.assertEquals(stats, verify_group_stats)
+
+
+class mpls_forwarding_group_l2tag(base_tests.SimpleDataPlane):
+ """chip not support
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_vid=1
+ test_port=config["port_map"].keys()[0]
+ index=1
+ #ref l2_intf_group
+ l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(self.controller, test_port, test_vid, False, False)
+
+ mpls_fwd_gid, mpls_fwd_msg=add_mpls_forwarding_group(self.controller,
+ subtype=OFDPA_MPLS_GROUP_SUBTYPE_L2_TAG,
+ index=1,
+ ref_gids=l2_intf_gid,
+ watch_port=None,
+ watch_group=None,
+ push_vlan=None,
+ pop_vlan=None,
+ set_vid=1)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=[]
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=l2_intf_msg.group_type,
+ group_id=l2_intf_msg.group_id,
+ buckets=l2_intf_msg.buckets)
+ )
+
+ verify_group_stats.append(ofp.group_desc_stats_entry(
+ group_type=mpls_fwd_msg.group_type,
+ group_id=mpls_fwd_msg.group_id,
+ buckets=mpls_fwd_msg.buckets)
+ )
+ verify_group_stats=sorted(verify_group_stats, key=getkey("group_id"))
+ stats=sorted(stats, key=getkey("group_id"))
+
+ self.assertEquals(stats, verify_group_stats)
\ No newline at end of file
diff --git a/Fabric/Utilities/accton/nat.py b/Fabric/Utilities/accton/nat.py
new file mode 100755
index 0000000..5557d60
--- /dev/null
+++ b/Fabric/Utilities/accton/nat.py
@@ -0,0 +1,293 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+Nat Test
+
+Test each flow table can set entry, and packet rx correctly.
+"""
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+from oftest.testutils import *
+from accton_util import *
+
+class dnat(base_tests.SimpleDataPlane):
+ """
+ [DNAT]
+ DNAT (inbound)
+
+ Inject eth 1/3 DA000000000200, SA000000000201, Tag 200, SIP 200.0.0.1, DIP 100.0.0.01, Sport 2828, Dport 5000
+ Output eth 1/1 DA000000000101, SA000000000100, Tag 100, SIP 200.0.0.1, DIP 10.0.0.01, Sport 2828, Dport 2000
+
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=10,cmd=add,prio=101 in_port=3,vlan_vid=0x10c8/0x1fff goto:20
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x640001 group=any,port=any,weight=0 output=1
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x23000001 group=any,port=any,weight=0 set_field=eth_src=00:00:00:00:01:00,set_field=eth_dst=00:00:00:00:01:01,set_field=vlan_vid=100,group=0x640001
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=20,cmd=add,prio=201 vlan_vid=200/0xfff,eth_dst=00:00:00:00:02:00,eth_type=0x0800 goto:28
+ ./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=0x23000001 goto:60
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_ports = sorted(config["port_map"].keys())
+
+ input_port = test_ports[0]
+ output_port = test_ports[1]
+
+ add_one_vlan_table_flow(self.controller, input_port, vlan_id=200, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False)
+ add_termination_flow(self.controller, input_port, 0x0800, [0x00,0x00,0x00,0x00,0x02,0x00], 200, goto_table=28, send_barrier=False)
+
+ add_one_l2_interface_group(self.controller, port=output_port, vlan_id=100, is_tagged=True, send_barrier=False)
+ msg1=add_l3_unicast_group(self.controller, port=output_port, vlanid=100, id=0x3000001, src_mac=[0x00,0x00,0x00,0x00,0x01,0x00], dst_mac=[0x00,0x00,0x00,0x00,0x01,0x01])
+ add_dnat_flow(self.controller, eth_type=0x0800, ip_dst=0x64000001, ip_proto=6, tcp_dst=5000, set_ip_dst=0x0a000001, set_tcp_dst=2000, action_group_id=msg1.group_id)
+
+ input_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:02:00",
+ eth_src="00:00:00:00:02:01",
+ dl_vlan_enable = True,
+ vlan_vid = 200,
+ ip_ttl=64,
+ ip_src="200.0.0.1",
+ ip_dst='100.0.0.1',
+ tcp_dport=5000)
+ output_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:01:01",
+ eth_src="00:00:00:00:01:00",
+ dl_vlan_enable = True,
+ vlan_vid = 100,
+ ip_ttl=63,
+ ip_src="200.0.0.1",
+ ip_dst='10.0.0.1',
+ tcp_dport=2000)
+
+ self.dataplane.send(input_port, str(input_pkt))
+ verify_packet(self, str(output_pkt), output_port)
+
+
+
+class dnatEcmp(base_tests.SimpleDataPlane):
+ """
+ [DNAT ECMP]
+ DNAT (inbound) with ECMP
+
+ Inject eth 1/3 DA000000000200, SA000000000201, Tag 200, SIP 200.0.0.1, DIP 100.0.0.01, Sport 2828, Dport 5000 [increase SIP]
+ Output eth 1/1 DA000000000101, SA000000000100, Tag 100, SIP 200.0.0.X, DIP 10.0.0.01, Sport 2828, Dport 2000
+ Output eth 1/5 DA000005224466, SA000005223355, Tag 2, SIP 200.0.0.X, DIP 10.0.0.01, Sport 2828, Dport 2000
+
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=10,cmd=add,prio=101 in_port=3,vlan_vid=0x10c8/0x1fff goto:20
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x640001 group=any,port=any,weight=0 output=1
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x23000001 group=any,port=any,weight=0 set_field=eth_src=00:00:00:00:01:00,set_field=eth_dst=00:00:00:00:01:01,set_field=vlan_vid=100,group=0x640001
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x20005 group=any,port=any,weight=0 output=5
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x23000005 group=any,port=any,weight=0 set_field=eth_src=00:00:05:22:33:55,set_field=eth_dst=00:00:05:22:44:66,set_field=vlan_vid=2,group=0x20005
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=sel,group=0x71000001 group=any,port=any,weight=0 group=0x23000001 group=any,port=any,weight=0 group=0x23000005
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=20,cmd=add,prio=201 vlan_vid=200/0xfff,eth_dst=00:00:00:00:02:00,eth_type=0x0800 goto:28
+
+ ./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
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_ports = config["port_map"].keys()
+ input_port = test_ports[0]
+ output_port = test_ports[1]
+ output_port2 = test_ports[2]
+
+ add_one_vlan_table_flow(self.controller, input_port, vlan_id=200, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_TAG, send_barrier=False)
+ add_one_l2_interface_group(self.controller, port=output_port, vlan_id=100, is_tagged=True, send_barrier=False)
+ #Bits 27:24 is for realm id, so unicast group id give 0x3000001
+ msg1=add_l3_unicast_group(self.controller, port=output_port, vlanid=100, id=0x3000001, src_mac=[0x00,0x00,0x00,0x00,0x01,0x00], dst_mac=[0x00,0x00,0x00,0x00,0x01,0x01])
+ add_one_l2_interface_group(self.controller, port=output_port2, vlan_id=2, is_tagged=True, send_barrier=False)
+ #Bits 27:24 is for realm id, so unicast group id give 0x3000005
+ msg2=add_l3_unicast_group(self.controller, port=output_port2, vlanid=2, id=0x3000005, src_mac=[0x00,0x00,0x05,0x22,0x33,0x55], dst_mac=[0x00,0x00,0x05,0x22,0x44,0x66])
+ ecmp=add_l3_ecmp_group(self.controller, id=0x1000001, l3_ucast_groups=[msg1.group_id, msg2.group_id])
+ add_termination_flow(self.controller, 0, 0x0800, [0x00,0x00,0x00,0x00,0x02,0x00], 200, goto_table=28, send_barrier=False)
+ add_dnat_flow(self.controller, eth_type=0x0800, ip_dst=0x64000001, ip_proto=6, tcp_dst=5000, set_ip_dst=0x0a000001, set_tcp_dst=2000, action_group_id=ecmp.group_id)
+
+
+ input_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:02:00",
+ eth_src="00:00:00:00:02:01",
+ dl_vlan_enable = True,
+ vlan_vid = 200,
+ ip_ttl=64,
+ ip_src="200.0.0.1",
+ ip_dst='100.0.0.1',
+ tcp_dport=5000)
+ output_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:01:01",
+ eth_src="00:00:00:00:01:00",
+ dl_vlan_enable = True,
+ vlan_vid = 100,
+ ip_ttl=63,
+ ip_src="200.0.0.1",
+ ip_dst='10.0.0.1',
+ tcp_dport=2000)
+ output_pkt2 = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:05:22:44:66",
+ eth_src="00:00:05:22:33:55",
+ dl_vlan_enable = True,
+ vlan_vid = 2,
+ ip_ttl=63,
+ ip_src="200.0.0.1",
+ ip_dst='10.0.0.1',
+ tcp_dport=2000)
+
+ self.dataplane.send(input_port, str(input_pkt))
+ verify_packet(self, str(output_pkt2), output_port2)
+ #self.dataplane.send(input_port, str(input_pkt))
+ #verify_packet(self, str(output_pkt2), output_port2)
+
+class snat_ecmp(base_tests.SimpleDataPlane):
+ """
+ [SNAT ECMP]
+ SNAT (outbound) with ECMP
+
+ Inject eth 1/1 DA000000000100, SA000000000101, Tag 100, SIP 10.0.0.1, DIP 200.0.0.01, Sport 2000, Dport 2828 [increase DIP]
+ Output eth 1/3 DA000000000200, SA000000000201, Tag 200, SIP 100.0.0.1, DIP 200.0.0.X, Sport 5000, Dport 2828
+ Output eth 1/5 DA000000000500, SA000000000501, Tag 5, SIP 100.0.0.1, DIP 200.0.0.X, Sport 5000, Dport 2828
+
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=10,cmd=add,prio=101 in_port=1,vlan_vid=0x1064/0x1fff goto:20
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=20,cmd=add,prio=201 vlan_vid=100/0xfff,eth_dst=00:00:00:00:01:00,eth_type=0x0800 goto:29
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0xC80003 group=any,port=any,weight=0 output=3
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x22000002 group=any,port=any,weight=0 set_field=eth_src=00:00:00:00:02:00,set_field=eth_dst=00:00:00:00:02:01,set_field=vlan_vid=200,group=0xC80003
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x50005 group=any,port=any,weight=0 output=5
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x22000005 group=any,port=any,weight=0 set_field=eth_src=00:00:00:00:05:00,set_field=eth_dst=00:00:00:00:05:01,set_field=vlan_vid=5,group=0x50005
+
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=sel,group=0x71000001 group=any,port=any,weight=0 group=0x22000002 group=any,port=any,weight=0 group=0x22000005
+ ./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
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=30,cmd=add,prio=301 eth_type=0x0800,ip_dst=200.0.0.1/255.255.255.0 write:group=0x71000001 goto:60
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_ports = sorted(config["port_map"].keys())
+
+ input_port = test_ports[0]
+ output_port = test_ports[1]
+ output_port2 = test_ports[2]
+
+ add_one_vlan_table_flow(self.controller, input_port, vlan_id=100, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_TAG, send_barrier=False)
+ add_termination_flow(self.controller, 0, 0x0800, [0x00,0x00,0x00,0x00,0x01,0x00], 100, goto_table=29, send_barrier=False)
+ add_one_l2_interface_group(self.controller, port=output_port, vlan_id=200, is_tagged=True, send_barrier=False)
+ #Bits 27:24 is for realm id, so unicast group id give 0x2000002
+ msg1=add_l3_unicast_group(self.controller, port=output_port, vlanid=200, id=0x2000002, src_mac=[0x00,0x00,0x00,0x00,0x02,0x00], dst_mac=[0x00,0x00,0x00,0x00,0x02,0x01])
+
+ add_one_l2_interface_group(self.controller, port=output_port2, vlan_id=5, is_tagged=True, send_barrier=False)
+ #Bits 27:24 is for realm id, so unicast group id give 0x2000002
+ msg2=add_l3_unicast_group(self.controller, port=output_port2, vlanid=5, id=0x2000005, src_mac=[0x00,0x00,0x00,0x00,0x05,0x00], dst_mac=[0x00,0x00,0x00,0x00,0x05,0x01])
+
+ ecmp=add_l3_ecmp_group(self.controller, id=0x1000001, l3_ucast_groups=[msg1.group_id, msg2.group_id])
+ add_snat_flow(self.controller, 0x0800, 0x0a000001, 6, 2000, 0x64000001, 5000)
+ add_unicast_routing_flow(self.controller, 0x0800, 0xc8000001, 0xffffff00, ecmp.group_id, vrf=0, send_barrier=False)
+
+ input_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:01:00",
+ eth_src="00:00:00:00:01:01",
+ dl_vlan_enable = True,
+ vlan_vid = 100,
+ ip_ttl=64,
+ ip_src='10.0.0.1',
+ ip_dst="200.0.0.1",
+ tcp_sport=2000)
+ output_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:02:01",
+ eth_src="00:00:00:00:02:00",
+ dl_vlan_enable = True,
+ vlan_vid = 200,
+ ip_ttl=63,
+ ip_src="100.0.0.1",
+ ip_dst='200.0.0.1',
+ tcp_sport=5000)
+ output_pkt2 = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:00:00:05:01",
+ eth_src="00:00:00:00:05:00",
+ dl_vlan_enable = True,
+ vlan_vid = 5,
+ ip_ttl=63,
+ ip_src="100.0.0.1",
+ ip_dst='200.0.0.1',
+ tcp_sport=5000)
+
+ self.dataplane.send(input_port, str(input_pkt))
+ verify_packet(self, str(output_pkt), output_port)
+ #self.dataplane.send(input_port, str(input_pkt))
+ #verify_packet(self, str(output_pkt2), output_port2)
+
+"""just for verify it can work after nat ecmp"""
+class l3Route(base_tests.SimpleDataPlane):
+ """
+ [L3 unicast route]
+ Do unicast route and output to specified port
+
+ Inject eth 1/3 Tag2, SA000000112233, DA7072cf7cf3a3, SIP 192.168.1.100, DIP 192.168.2.2
+ Output eth 1/1 Tag3, SA 000004223355, DA 000004224466
+
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=0,cmd=add,prio=1 in_port=0/0xffff0000 goto:10
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=10,cmd=add,prio=101 in_port=3,vlan_vid=0x1002/0x1fff goto:20
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=20,cmd=add,prio=201 in_port=3,vlan_vid=2/0xfff,eth_dst=70:72:cf:7c:f3:a3,eth_type=0x0800 goto:30
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x30001 group=any,port=any,weight=0 output=1
+ ./dpctl tcp:192.168.1.1:6633 group-mod cmd=add,type=ind,group=0x20000003 group=any,port=any,weight=0 set_field=eth_src=00:00:04:22:33:55,set_field=eth_dst=00:00:04:22:44:66,set_field=vlan_vid=3,group=0x30001
+ ./dpctl tcp:192.168.1.1:6633 flow-mod table=30,cmd=add,prio=301 eth_type=0x0800,ip_dst=192.168.2.2/255.255.255.0 write:group=0x20000003 goto:60
+ """
+ def runTest(self):
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ test_ports = sorted(config["port_map"].keys())
+
+ input_port = test_ports[0]
+ output_port = test_ports[1]
+
+ add_port_table_flow(self.controller, is_overlay=False)
+ add_one_vlan_table_flow(self.controller, input_port, vlan_id=2, vrf=0, flag=VLAN_TABLE_FLAG_ONLY_TAG, send_barrier=False)
+ add_termination_flow(self.controller, input_port, 0x0800, [0x70, 0x72, 0xcf, 0x7c, 0xf3, 0xa3], 2, send_barrier=False)
+ add_one_l2_interface_group(self.controller, port=output_port, vlan_id=3, is_tagged=True, send_barrier=False)
+ msg=add_l3_unicast_group(self.controller, port=output_port, vlanid=3, id=3, src_mac=[0x00,0x00,0x04,0x22,0x33,0x55], dst_mac=[0x00,0x00,0x04,0x22,0x44,0x66])
+ add_unicast_routing_flow(self.controller, 0x0800, 0xc0a80202, 0xffffff00, msg.group_id)
+
+ #verify tx/rx packet
+ input_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="70:72:cf:7c:f3:a3",
+ eth_src="00:00:00:00:02:01",
+ dl_vlan_enable = True,
+ vlan_vid = 2,
+ ip_ttl=64,
+ ip_src="200.0.0.1",
+ ip_dst='192.168.2.2')
+ output_pkt = simple_tcp_packet(pktlen=100,
+ eth_dst="00:00:04:22:44:66",
+ eth_src="00:00:04:22:33:55",
+ dl_vlan_enable = True,
+ vlan_vid = 3,
+ ip_ttl=63,
+ ip_src="200.0.0.1",
+ ip_dst='192.168.2.2')
+
+ self.dataplane.send(input_port, str(input_pkt))
+ verify_packet(self, str(output_pkt), output_port)
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Fabric/Utilities/accton/vxlan_flow_test.py b/Fabric/Utilities/accton/vxlan_flow_test.py
new file mode 100755
index 0000000..b57b98e
--- /dev/null
+++ b/Fabric/Utilities/accton/vxlan_flow_test.py
@@ -0,0 +1,1281 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+Flow Test
+
+Test each flow table can set entry, and packet rx correctly.
+"""
+
+import logging
+
+from oftest import config
+import oftest.base_tests as base_tests
+import ofp
+from oftest.testutils import *
+from accton_util import *
+import oftest.parse as decode
+
+class VxlanConfigNetconf(base_tests.SimpleDataPlane):
+ """
+ Verify netconf to configure Vxlan port
+ """
+ def runTest(self):
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ #paramaters
+ access_port_vid=1
+ access_phy_port=1
+ access_lport=0x10001
+ vnid=103
+ next_hop_id=1
+ next_hop_id_mcast=2
+ dst_mac="00:00:11:22:22:11"
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ network_port_phy_port=2
+ network_lport=0x10002
+ network_port_vlan=2
+ network_port_sip="192.168.1.1"
+ network_port_dip="192.168.2.1"
+
+ xml_before=get_edit_config(config["switch_ip"])
+ #get datapath_id from feature message
+ feature_reply=get_featureReplay(self)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id_mcast, dst_mac_mcast, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid,
+ mcast_ipv4=mcast_ipv4,
+ next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport, phy_port=access_phy_port,
+ vlan=access_port_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport, access_phy_port, access_port_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport, network_port_sip, network_port_dip, next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ get_edit_config(config["switch_ip"])
+
+ #exit verification so clear all configuration
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport, phy_port=access_phy_port,
+ vlan=access_port_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid,
+ mcast_ipv4=mcast_ipv4,
+ next_hop_id=next_hop_id_mcast, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ xml_after=get_edit_config(config["switch_ip"])
+ #logging.info("xml_before\n %s", xml_before)
+ #logging.info("xml_after\n %s", xml_after)
+ #netopeer may have problem on xml process
+ #assert(xml_before == xml_after)
+
+class OverlayFloodGroup(base_tests.SimpleDataPlane):
+ """
+ create two lport
+ """
+ def runTest(self):
+ """
+ first verify flood over unicast,
+ second verify flood over mcast
+ """
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ #paramaters
+ access_port_vid=1
+ access_phy_port=1
+ access_lport=0x10001
+ vnid=103
+ next_hop_id=1
+ next_hop_id_mcast=2
+ dst_mac="00:00:11:22:22:11"
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ network_port_phy_port=2
+ network_lport=0x10002
+ network_port_vlan=2
+ network_port_sip="192.168.1.1"
+ network_port_dip="192.168.2.1"
+
+ feature_reply=get_featureReplay(self)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport, phy_port=access_phy_port,
+ vlan=access_port_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport, access_phy_port, access_port_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport, network_port_sip, network_port_dip, next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ #add flow over unicast group
+ msg=add_l2_overlay_flood_over_unicast_tunnel_group(self.controller, vnid, [access_lport, network_lport], 1)
+ #verify
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+ verify_group_stats=(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets))
+
+ self.assertEquals(stats, [verify_group_stats])
+ #clear all group
+ delete_all_groups(self.controller)
+ #
+ #flood over mcast
+ msg=add_l2_overlay_flood_over_mcast_tunnel_group(self.controller, vnid, [access_lport, network_lport], 1)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets))
+
+ self.assertEquals(stats, [verify_group_stats])
+ #clear all group
+ delete_all_groups(self.controller)
+ #exit verification so clear all configuration
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport, phy_port=access_phy_port,
+ vlan=access_port_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+class OverlayMcastGroup(base_tests.SimpleDataPlane):
+ """
+ create two lport
+ """
+ def runTest(self):
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+ #paramaters
+ access_port_vid=1
+ access_phy_port=1
+ access_lport=0x10001
+ vnid=103
+ next_hop_id=1
+ next_hop_id_mcast=2
+ dst_mac="00:00:11:22:22:11"
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ network_port_phy_port=2
+ network_lport=0x10002
+ network_port_vlan=2
+ network_port_sip="192.168.1.1"
+ network_port_dip="192.168.2.1"
+
+ feature_reply=get_featureReplay(self)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport, phy_port=access_phy_port,
+ vlan=access_port_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport, access_phy_port, access_port_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport, network_port_sip, network_port_dip, next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ #add flow over unicast group
+ msg=msg=add_l2_overlay_mcast_over_unicast_tunnel_group(self.controller, vnid, [access_lport, network_lport], 1)
+ #verify
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+ verify_group_stats=(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets))
+
+ self.assertEquals(stats, [verify_group_stats])
+ #clear all group
+ delete_all_groups(self.controller)
+ #
+ #flood over mcast
+ msg=add_l2_overlay_mcast_over_mcast_tunnel_group(self.controller, vnid, [access_lport, network_lport], 1)
+
+ stats = get_stats(self, ofp.message.group_desc_stats_request())
+
+ verify_group_stats=(ofp.group_desc_stats_entry(
+ group_type=msg.group_type,
+ group_id=msg.group_id,
+ buckets=msg.buckets))
+
+ self.assertEquals(stats, [verify_group_stats])
+ #clear all group
+ delete_all_groups(self.controller)
+ #exit verification so clear all configuration
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport, phy_port=access_phy_port,
+ vlan=access_port_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+class AccessToNetworkDLFMcast(base_tests.SimpleDataPlane):
+ def runTest(self):
+ """
+ first verify flood over unicast,
+ second verify flood over mcast
+ """
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ access_port1_vid=1
+ access_phy_port1=config["port_map"].keys()[0]
+ access_lport1=0x10001
+ access_port2_vid=0
+ access_phy_port2=config["port_map"].keys()[1]
+ access_lport2=0x10002
+ vnid=10
+ next_hop_id=1
+ next_hop_id_mcast=2
+ dst_mac="00:00:11:22:22:11"
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ network_port_phy_port=config["port_map"].keys()[2]
+ network_lport=0x10003
+ network_port_vlan=2
+ network_port_sip="192.168.1.1"
+ network_port_dip="192.168.2.1"
+
+ feature_reply=get_featureReplay(self)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport1, access_phy_port1, access_port1_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport2, access_phy_port2, access_port2_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport, network_port_sip, network_port_dip, next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ #get_edit_config(config["switch_ip"])
+
+ #add port table to have vxlan ability
+ add_port_table_flow(self.controller)
+
+ #for network port need l2 interface group to decide vlan tag or not
+ add_one_l2_interface_group(self.controller, network_port_phy_port, vlan_id=network_port_vlan)
+
+ #add DLF bridge flow
+ msg=add_l2_overlay_flood_over_mcast_tunnel_group(self.controller, vnid, [access_lport1, access_lport2, network_lport], 1)
+ add_overlay_bridge_flow(self.controller, None, vnid, msg.group_id, True, True)
+
+ #send packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst='00:00:11:11:11:11')
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ #vxlan packet IP header have some parmater decide by HW,
+ #we can easy to check VxLAN IP header
+ verify_packet(self, pkt, network_port_phy_port)
+ verify_no_other_packets(self)
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0x9a], vnid, network_lport, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:9a',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on network port
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst='00:12:34:56:78:9a')
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, network_port_phy_port)
+ verify_no_other_packets(self)
+
+ #exit verification so clear all configuration
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+class AccessToNetworkDLFUcast(base_tests.SimpleDataPlane):
+ def runTest(self):
+ """
+ first verify flood over unicast,
+ second verify flood over mcast
+ """
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ access_port1_vid=1
+ access_phy_port1=config["port_map"].keys()[0]
+ access_lport1=0x10001
+ access_port2_vid=0
+ access_phy_port2=config["port_map"].keys()[1]
+ access_lport2=0x10002
+ vnid=10
+ next_hop_id=1
+ next_hop_id_mcast=2
+ dst_mac="00:00:11:22:22:11"
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ network_port_phy_port=config["port_map"].keys()[2]
+ network_lport=0x10003
+ network_port_vlan=2
+ network_port_sip="192.168.1.1"
+ network_port_dip="192.168.2.1"
+
+ feature_reply=get_featureReplay(self)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport1, access_phy_port1, access_port1_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport2, access_phy_port2, access_port2_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport, network_port_sip, network_port_dip, next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ #get_edit_config(config["switch_ip"])
+
+ #add port table to have vxlan ability
+ add_port_table_flow(self.controller)
+
+ #for network port need l2 interface group to decide vlan tag or not
+ add_one_l2_interface_group(self.controller, network_port_phy_port, vlan_id=network_port_vlan)
+
+ #add DLF bridge flow
+ msg=add_l2_overlay_flood_over_unicast_tunnel_group(self.controller, vnid, [access_lport1, access_lport2, network_lport], 1)
+ add_overlay_bridge_flow(self.controller, None, vnid, msg.group_id, True, True)
+
+ #send packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst='00:00:11:11:11:11')
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ #vxlan packet IP header have some parmater decide by HW,
+ #we can easy to check VxLAN IP header
+ verify_packet(self, pkt, network_port_phy_port)
+ verify_no_other_packets(self)
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0x9a], vnid, network_lport, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:9a',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on network port
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst='00:12:34:56:78:9a')
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, network_port_phy_port)
+ verify_no_other_packets(self)
+
+ #exit verification so clear all configuration
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+class AccessWithAccessDiffPortVlan(base_tests.SimpleDataPlane):
+ def runTest(self):
+ """
+ first verify flood over unicast,
+ second verify flood over mcast
+ """
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ access_port1_vid=1
+ access_phy_port1=config["port_map"].keys()[0]
+ access_lport1=0x10001
+ access_port2_vid=0
+ access_phy_port2=config["port_map"].keys()[1]
+ access_lport2=0x10002
+ access_port3_vid=3
+ access_phy_port3=config["port_map"].keys()[2]
+ access_lport3=0x10003
+ vnid=10
+ next_hop_id_mcast=1
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+
+ feature_reply=get_featureReplay(self)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=access_phy_port3,
+ vlan=access_port3_vid)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id_mcast, dst_mac_mcast, access_phy_port3, access_port3_vid);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport1, access_phy_port1, access_port1_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport2, access_phy_port2, access_port2_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport3, phy_port=access_phy_port3,
+ vlan=access_port3_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport3, access_phy_port3, access_port3_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+
+ #add port table to have vxlan ability
+ add_port_table_flow(self.controller)
+
+ #add DLF bridge flow
+ msg=add_l2_overlay_flood_over_mcast_tunnel_group(self.controller, vnid, [access_lport1, access_lport2, access_lport3], 1)
+ add_overlay_bridge_flow(self.controller, None, vnid, msg.group_id, True, True)
+
+ #send packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+
+ #verify packet on access port 2, vid=0, so untag
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst='00:00:11:11:11:11')
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ #verify packet on access port 3
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable= True,
+ vlan_vid=access_port3_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port3)
+ verify_no_other_packets(self)
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0x9a], vnid, access_lport2, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:9a',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst='00:12:34:56:78:9a')
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ verify_no_other_packets(self)
+
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0xaa], vnid, access_lport3, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:aa',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:aa',
+ dl_vlan_enable= True,
+ vlan_vid=access_port3_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port3)
+ verify_no_other_packets(self)
+
+
+
+ #exit verification so clear all configuration
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport3, phy_port=access_phy_port3,
+ vlan=access_port3_vid, vnid=vnid, operation="delete")
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport3, access_phy_port3, access_port3_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=access_phy_port3,
+ vlan=access_port3_vid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+
+class AccessWithAccessSamePortDiffVlan(base_tests.SimpleDataPlane):
+ def runTest(self):
+ """
+ first verify flood over unicast,
+ second verify flood over mcast
+ """
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ access_port1_vid=1
+ access_phy_port1=config["port_map"].keys()[0]
+ access_lport1=0x10001
+ access_port2_vid=2
+ access_phy_port2= access_phy_port1
+ access_lport2=0x10002
+ access_port3_vid=3
+ access_phy_port3=access_phy_port1
+ access_lport3=0x10003
+ vnid=10
+ next_hop_id_mcast=1
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+
+ feature_reply=get_featureReplay(self)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=access_phy_port3,
+ vlan=access_port3_vid)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id_mcast, dst_mac_mcast, access_phy_port3, access_port3_vid);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport1, access_phy_port1, access_port1_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport2, access_phy_port2, access_port2_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport3, phy_port=access_phy_port3,
+ vlan=access_port3_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport3, access_phy_port3, access_port3_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+
+ #add port table to have vxlan ability
+ add_port_table_flow(self.controller)
+
+ #add DLF bridge flow
+ msg=add_l2_overlay_flood_over_mcast_tunnel_group(self.controller, vnid, [access_lport1, access_lport2, access_lport3], 1)
+ add_overlay_bridge_flow(self.controller, None, vnid, msg.group_id, True, True)
+
+ #send packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+
+ #verify packet on access port 2, vid=0, so untag
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable = True,
+ vlan_vid = access_port2_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ #verify packet on access port 3
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:00:11:11:11:11',
+ dl_vlan_enable= True,
+ vlan_vid=access_port3_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port3)
+ verify_no_other_packets(self)
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0x9a], vnid, access_lport2, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:9a',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:9a',
+ dl_vlan_enable = True,
+ vlan_vid = access_port2_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ verify_no_other_packets(self)
+
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0xaa], vnid, access_lport3, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:aa',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:aa',
+ dl_vlan_enable= True,
+ vlan_vid=access_port3_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port3)
+ verify_no_other_packets(self)
+
+ add_overlay_bridge_flow(self.controller, [0x00, 0x12, 0x34, 0x56, 0x78, 0xbb], vnid, access_lport2, False, True)
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:bb',
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on access port
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst='00:12:34:56:78:bb',
+ dl_vlan_enable= True,
+ vlan_vid=access_port2_vid)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, access_phy_port2)
+ verify_no_other_packets(self)
+
+ #exit verification so clear all configuration
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport3, phy_port=access_phy_port3,
+ vlan=access_port3_vid, vnid=vnid, operation="delete")
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport3, access_phy_port3, access_port3_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=access_phy_port3,
+ vlan=access_port3_vid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+
+class AccessWithNetwork(base_tests.SimpleDataPlane):
+ def runTest(self):
+ """
+ first verify flood over unicast,
+ second verify flood over mcast
+ """
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ access_port1_vid=1
+ access_phy_port1=config["port_map"].keys()[0]
+ access_lport1=0x10001
+ access_lport1_mac=[0x00, 0x00, 0x00, 0x77, 0x77, 0x77]
+ access_lport1_mac_str=(":".join(map(str, map(hex, access_lport1_mac)))).replace("0x", "")
+ access_port2_vid=0
+ access_phy_port2=config["port_map"].keys()[1]
+ access_lport2=0x10002
+ access_lport2_mac=[0x00,0x00, 0x00, 0x00, 0x00, 0x02]
+ access_lport2_mac_str=(":".join(map(str, map(hex, access_lport2_mac)))).replace("0x", "")
+ vnid=10
+ next_hop_id=1
+ next_hop_id_mcast=2
+ dst_mac="00:00:11:22:22:11"
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ network_port_phy_port=config["port_map"].keys()[2]
+ network_lport=0x10003
+ network_port_vlan=2
+ network_port_sip="192.168.1.1"
+ network_port_dip="192.168.2.1"
+ network_lport_mac=[0x00,0x00, 0x00, 0x00, 0x00, 0x03]
+ network_lport_mac_str=(":".join(map(str, map(hex, network_lport_mac)))).replace("0x", "")
+
+
+
+ feature_reply=get_featureReplay(self)
+ #get switch CPU mac
+ str_datapath_id_f= "{:016x}".format(feature_reply.datapath_id)
+ str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
+ switch_cpu_mac_str=str_datapath_id[6:]
+ switch_cpu_mac = switch_cpu_mac_str.split(":")
+ switch_cpu_mac=[int(switch_cpu_mac[i],16) for i in range(0, len(switch_cpu_mac))]
+
+ #add config vtep/vtap/nexthop/vni
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id, dst_mac, network_port_phy_port, network_port_vlan);
+
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ #vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport1, access_phy_port1, access_port1_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport2, access_phy_port2, access_port2_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport, network_port_sip, network_port_dip, next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ #add port table to have vxlan ability
+ add_port_table_flow(self.controller)
+ add_port_table_flow(self.controller, is_overlay=False)
+
+ #for network port need l2 interface group to decide vlan tag or not
+ add_one_l2_interface_group(self.controller, network_port_phy_port, vlan_id=network_port_vlan)
+ #add network mac
+ add_overlay_bridge_flow(self.controller, network_lport_mac, vnid, network_lport, False, True)
+ add_overlay_bridge_flow(self.controller, access_lport1_mac, vnid, access_lport1, False, True)
+
+ #add termination table for network port
+ add_termination_flow(self.controller, in_port=network_port_phy_port, eth_type=0x0800,
+ dst_mac=switch_cpu_mac, vlanid=network_port_vlan)
+ #add vlan table for network port rx packet class vlan
+ add_one_vlan_table_flow(self.controller, of_port=network_port_phy_port,
+ vlan_id=network_port_vlan)
+
+ #tx packet on access lport 1
+ parsed_pkt = simple_udp_packet(pktlen=96, eth_dst=network_lport_mac_str,
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+ pkt = str(parsed_pkt)
+ self.dataplane.send(access_phy_port1, pkt)
+ #verify packet on network port
+ #need find a way to verify vxlan header
+ parsed_pkt = simple_udp_packet(pktlen=92, eth_dst=network_lport_mac_str)
+ pkt = str(parsed_pkt)
+ verify_packet(self, pkt, network_port_phy_port)
+ verify_no_other_packets(self)
+
+ #tx packet on network lport
+ inner_pkt = simple_udp_packet(pktlen=96, eth_dst=access_lport1_mac_str)
+ vxlan_pkt = simple_vxlan_packet(eth_dst=switch_cpu_mac_str,
+ vnid=vnid,
+ ip_dst= network_port_sip,
+ ip_src=network_port_dip,
+ inner_payload=inner_pkt)
+ self.dataplane.send(network_port_phy_port, str(vxlan_pkt))
+ #verify
+ inner_pkt = simple_udp_packet(pktlen=100, eth_dst=access_lport1_mac_str,
+ dl_vlan_enable= True,
+ vlan_vid=access_port1_vid)
+
+ verify_packet(self, inner_pkt, access_phy_port1)
+ verify_no_other_packets(self)
+
+
+ #exit verification so clear all configuration
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport2, phy_port=access_phy_port2,
+ vlan=access_port2_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport,
+ src_ip=network_port_sip, dst_ip=network_port_dip,
+ next_hop_id=next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id,
+ dst_mac=dst_mac,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port_phy_port,
+ vlan=network_port_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
+class NetworkToNetwork(base_tests.SimpleDataPlane):
+ def runTest(self):
+ """
+ This case can't work, can't identify it is chip limitation or not
+ """
+ return
+ if config["switch_ip"] == None:
+ logging.error("Doesn't configure switch IP")
+ return
+
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vnid=10
+ mcast_ipv4="224.1.1.1"
+ dst_mac_mcast="01:00:5e:01:01:01"
+ next_hop_id_mcast=3
+
+ access_port1_vid=1
+ access_phy_port1=config["port_map"].keys()[0]
+ access_lport1=0x10001
+
+ network_port1_phy_port=config["port_map"].keys()[1]
+ network_lport1=0x10003
+ network_port1_vlan=2
+ network_port1_sip="192.168.1.1"
+ network_port1_dip="192.168.2.1"
+ network_port1_next_hop_id=1
+ network_port1_dst_mac="00:00:11:22:22:11"
+ network_lport1_mac=[0x00,0x00, 0x00, 0x00, 0x00, 0x33]
+ network_lport1_mac_str=(":".join(map(str, map(hex, network_lport1_mac)))).replace("0x", "")
+
+ network_port2_phy_port=config["port_map"].keys()[2]
+ network_lport2=0x10004
+ network_port2_vlan=3
+ network_port2_sip="192.168.3.1"
+ network_port2_dip="192.168.4.1"
+ network_port2_next_hop_id=2
+ network_port2_dst_mac="00:00:11:22:22:22"
+ network_lport2_mac=[0x00,0x00, 0x00, 0x00, 0x00, 0x44]
+ network_lport2_mac_str=(":".join(map(str, map(hex, network_lport2_mac)))).replace("0x", "")
+
+ feature_reply=get_featureReplay(self)
+ #get switch CPU mac
+ str_datapath_id_f= "{:016x}".format(feature_reply.datapath_id)
+ str_datapath_id=':'.join([str_datapath_id_f[i:i+2] for i in range(0, len(str_datapath_id_f), 2)])
+ switch_cpu_mac_str=str_datapath_id[6:]
+ switch_cpu_mac = switch_cpu_mac_str.split(":")
+ switch_cpu_mac=[int(switch_cpu_mac[i],16) for i in range(0, len(switch_cpu_mac))]
+ #config vlxan
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=network_port1_next_hop_id,
+ dst_mac=network_port1_dst_mac,
+ phy_port=network_port1_phy_port,
+ vlan=network_port1_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", network_port1_next_hop_id, network_port1_dst_mac, network_port1_phy_port, network_port1_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=network_port2_next_hop_id,
+ dst_mac=network_port2_dst_mac,
+ phy_port=network_port2_phy_port,
+ vlan=network_port2_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", network_port2_next_hop_id, network_port2_dst_mac, network_port2_phy_port, network_port2_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port1_phy_port,
+ vlan=network_port1_vlan)
+ logging.info("config NextHop %d, DST_MAC %s, PHY %d, VLAN %d", next_hop_id_mcast, dst_mac_mcast, network_port1_phy_port, network_port1_vlan);
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml)==True)
+
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=mcast_ipv4, next_hop_id=next_hop_id_mcast)
+ logging.info("config VNI %lx", vnid);
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid)
+ logging.info("config VTAP 0x%lx, PHY %d, VID %d, VNID %lx", access_lport1, access_phy_port1, access_port1_vid, vnid);
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport1,
+ src_ip=network_port1_sip, dst_ip=network_port1_dip,
+ next_hop_id=network_port1_next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport1, network_port1_sip, network_port1_dip, network_port1_next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport2,
+ src_ip=network_port2_sip, dst_ip=network_port2_dip,
+ next_hop_id=network_port2_next_hop_id,
+ vnid=vnid)
+ logging.info("config VTEP 0x%lx, SRC_IP %s, DST_IP %s, NEXTHOP_ID %d", network_lport2, network_port2_sip, network_port2_dip, network_port2_next_hop_id);
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+
+ #add port table to have vxlan ability
+ add_port_table_flow(self.controller)
+
+ #for network port need l2 interface group to decide vlan tag or not
+ add_one_l2_interface_group(self.controller, network_port1_phy_port, vlan_id=network_port1_vlan)
+ add_one_l2_interface_group(self.controller, network_port2_phy_port, vlan_id=network_port2_vlan)
+ #add network mac
+ add_overlay_bridge_flow(self.controller, network_lport1_mac, vnid, network_lport1, False, True)
+ add_overlay_bridge_flow(self.controller, network_lport2_mac, vnid, network_lport2, False, True)
+
+ #add termination table for network port
+ add_termination_flow(self.controller, in_port=network_port1_phy_port, eth_type=0x0800,
+ dst_mac=switch_cpu_mac, vlanid=network_port1_vlan)
+ add_termination_flow(self.controller, in_port=network_port2_phy_port, eth_type=0x0800,
+ dst_mac=switch_cpu_mac, vlanid=network_port2_vlan)
+ #add vlan table for network port rx packet class vlan
+ add_one_vlan_table_flow(self.controller, of_port=network_port1_phy_port,
+ vlan_id=network_port1_vlan)
+ add_one_vlan_table_flow(self.controller, of_port=network_port2_phy_port,
+ vlan_id=network_port2_vlan)
+
+ #packet tx on network port 1 rx on network port 2
+ inner_pkt = simple_udp_packet(pktlen=96, eth_dst=network_lport2_mac_str)
+ vxlan_pkt = simple_vxlan_packet(eth_dst=switch_cpu_mac_str,
+ vnid=vnid,
+ ip_dst= network_port1_sip,
+ ip_src=network_port1_dip,
+ inner_payload=inner_pkt)
+ self.dataplane.send(network_port1_phy_port, str(vxlan_pkt))
+ #verify
+ verify_packet(self, str(inner_pkt), network_port2_phy_port)
+ verify_no_other_packets(self)
+
+
+
+ #exit verification so clear all configuration
+ delete_all_flows(self.controller)
+ delete_all_groups(self.controller)
+
+ vtap_conf_xml=get_vtap_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=access_lport1, phy_port=access_phy_port1,
+ vlan=access_port1_vid, vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtap_conf_xml) == True)
+
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport1,
+ src_ip=network_port1_sip, dst_ip=network_port1_dip,
+ next_hop_id=network_port1_next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+ vtep_conf_xml=get_vtep_lport_config_xml(dp_id=feature_reply.datapath_id,
+ lport=network_lport2,
+ src_ip=network_port2_sip, dst_ip=network_port2_dip,
+ next_hop_id=network_port2_next_hop_id,
+ vnid=vnid, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vtep_conf_xml) == True)
+ vni_config_xml=get_vni_config_xml(vni_id=vnid, mcast_ipv4=None, next_hop_id=None, operation="delete")
+ assert(send_edit_config(config["switch_ip"], vni_config_xml) == True)
+
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=network_port1_next_hop_id,
+ dst_mac=network_port1_dst_mac,
+ phy_port=network_port1_phy_port,
+ vlan=network_port1_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=network_port2_next_hop_id,
+ dst_mac=network_port2_dst_mac,
+ phy_port=network_port2_phy_port,
+ vlan=network_port2_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+ next_hop_conf_xml=get_next_hop_config_xml(next_hop_id=next_hop_id_mcast,
+ dst_mac=dst_mac_mcast,
+ phy_port=network_port1_phy_port,
+ vlan=network_port1_vlan, operation="delete")
+ assert(send_edit_config(config["switch_ip"], next_hop_conf_xml) == True)
+
\ No newline at end of file