add vxlan test case
diff --git a/accton/accton_util.py b/accton/accton_util.py
index 06cd438..239c38a 100755
--- a/accton/accton_util.py
+++ b/accton/accton_util.py
@@ -6,9 +6,13 @@
 import time
 from oftest.testutils import *
 
+from ncclient import manager
+import ncclient
+
 OFDPA_GROUP_TYPE_SHIFT=28
 OFDPA_VLAN_ID_SHIFT   =16
-OFDPA_TUNNEL_ID_SHIFT =16
+OFDPA_TUNNEL_ID_SHIFT =12
+OFDPA_TUNNEL_SUBTYPE_SHIFT=10
 
 #VLAN_TABLE_FLAGS
 VLAN_TABLE_FLAG_ONLY_UNTAG=1
@@ -39,12 +43,12 @@
 def encode_l3_ecmp_group_id(id):
     return id + (7 << OFDPA_GROUP_TYPE_SHIFT)
 
-def encode_l2_overlay_flood_group_id(tunnel_id, index):
-    return id + (tunnel_id << OFDPA_TUNNEL_ID_SHIFT)+(8 << 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 encode_l2_overlay_mcast_group_id(tunnel_id, index):
-    return id + (tunnel_id << OFDPA_TUNNEL_ID_SHIFT)+(9 << OFDPA_GROUP_TYPE_SHIFT)
-    
 def add_l2_interface_grouop(ctrl, ports, vlan_id=1, is_tagged=False, send_barrier=False):
     # group table
     # set up untag groups for each port
@@ -229,7 +233,78 @@
                                    )
     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))
+    else:
+       match.oxm_list.append(ofp.oxm.in_port(0))
+
+    request = ofp.message.flow_add(
+		table_id=0,
+		cookie=42,
+		match=match,
+		instructions=[
+		  ofp.instruction.goto_table(50)
+		],
+		priority=0)
+    logging.info("Add port table, match port %lx" % 0x10000)
+    ctrl.message_send(request)
+
 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
@@ -321,8 +396,11 @@
     
 def add_bridge_flow(ctrl, dst_mac, vlanid, group_id, send_barrier=False):
     match = ofp.match()
-    match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
+    if dst_mac!=None:
+        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,
@@ -343,18 +421,49 @@
         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, send_barrier=False):
     match = ofp.match()
-    match.oxm_list.append(ofp.oxm.in_port(in_port))
     match.oxm_list.append(ofp.oxm.eth_type(eth_type))
-    match.oxm_list.append(ofp.oxm.eth_dst(dst_mac))
-    match.oxm_list.append(ofp.oxm.vlan_vid(0x1000+vlanid))
-
-    if dst_mac[0]&0x01 == 0x01: #macast
-        goto_table=40
-    else:        
-        goto_table=30
+    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:
+       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))
+       goto_table=30
 
     request = ofp.message.flow_add(
             table_id=20,
@@ -400,4 +509,330 @@
     if send_barrier:
         do_barrier(ctrl)   
 
-    return request        
\ No newline at end of file
+    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(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 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(hex(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>VNID</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(hex(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:
+	    print m.get_config(source='running').data_xml