| import logging |
| |
| from oftest import config |
| import oftest.base_tests as base_tests |
| import ofp |
| 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 =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 |
| |
| 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_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_interface_grouop(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_grouop(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_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.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): |
| 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(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) |
| 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(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_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_add(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 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): |
| 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.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(0)) |
| 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 add_one_vlan_table_flow(ctrl, of_port, vlan_id=1, flag=VLAN_TABLE_FLAG_ONLY_BOTH, send_barrier=False): |
| # table 10: vlan |
| # goto to table 20 |
| 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_add( |
| table_id=10, |
| cookie=42, |
| match=match, |
| instructions=[ |
| 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(0)) |
| 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) |
| |
| if send_barrier: |
| do_barrier(ctrl) |
| |
| return request |
| |
| def add_bridge_flow(ctrl, dst_mac, vlanid, group_id, 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.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=1000) |
| |
| 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, 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: |
| 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, |
| 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, send_barrier=False): |
| match = ofp.match() |
| match.oxm_list.append(ofp.oxm.eth_type(eth_type)) |
| if mask!=0: |
| match.oxm_list.append(ofp.oxm.ipv4_dst_masked(dst_ip, mask)) |
| else: |
| match.oxm_list.append(ofp.oxm.ipv4_dst(dst_ip)) |
| |
| request = ofp.message.flow_add( |
| table_id=30, |
| 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 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_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 |
| |
| |
| 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 |