summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryyyIce <[email protected]>2020-04-24 00:45:04 +0800
committeryyyIce <[email protected]>2020-04-24 00:45:04 +0800
commit8acfaff12ad7f7b5bfb517ff8c6f697ed053237f (patch)
tree71628f3f1109a544542d495b82d8ae40a9411e7c
parent247bc895be2736913b0efc86c13435bea35e5697 (diff)
add 1.vlan_aggregation
-rw-r--r--vlan_aggregation/cmd.txt29
-rw-r--r--vlan_aggregation/p4src/vlan_aggregation.p4821
-rw-r--r--vlan_aggregation/ptf-tests/test.py1140
3 files changed, 1990 insertions, 0 deletions
diff --git a/vlan_aggregation/cmd.txt b/vlan_aggregation/cmd.txt
new file mode 100644
index 0000000..2e0d85c
--- /dev/null
+++ b/vlan_aggregation/cmd.txt
@@ -0,0 +1,29 @@
+#all ttys need to set $PATH
+cd ~/bf-sde-9.0.0
+. ~/tools/set_sde.bash
+
+#tty1
+~/tools/p4_build.sh ~/labs/simple_vlanagg/vlan_aggregation.p4
+sudo $SDE_INSTALL/bin/veth_setup.sh
+./run_tofino_model.sh -p vlan_aggregation
+
+#tty2
+./run_switchd.sh -p vlan_aggregation
+
+#tty3
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.HostSend
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.HostDrop
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.HostL3Switch
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.LpmSend
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.LpmDrop
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.LpmL3Switch
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.BadTTL
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.BadChecksum
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.ArpReply
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.DiffSubVLANSend
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.SameSubVLANSend
+./run_p4_tests.sh -p vlan_aggregation -t ~/labs/simple_vlanagg/ -s test.SameSubVLANSend
+
+
+#may use tty4
+./run_bfshell.sh
diff --git a/vlan_aggregation/p4src/vlan_aggregation.p4 b/vlan_aggregation/p4src/vlan_aggregation.p4
new file mode 100644
index 0000000..a2a33f8
--- /dev/null
+++ b/vlan_aggregation/p4src/vlan_aggregation.p4
@@ -0,0 +1,821 @@
+/* -*- P4_16 -*- */
+
+#include <core.p4>
+#include <tna.p4>
+
+
+/*************************************************************************
+ ************* C O N S T A N T S A N D T Y P E S *******************
+**************************************************************************/
+enum bit<16> ether_type_t {
+ IPV4 = 0x0800,
+ ARP = 0x0806,
+ TPID = 0x8100,
+ TPID2 = 0x9100,
+ IPV6 = 0x86DD
+}
+
+enum bit<8> ip_protocol_t {
+ ICMP = 1,
+ IGMP = 2,
+ TCP = 6,
+ UDP = 17
+}
+
+enum bit<16> arp_opcode_t {
+ REQUEST = 1,
+ REPLY = 2
+}
+
+enum bit<8> icmp_type_t {
+ ECHO_REPLY = 0,
+ ECHO_REQUEST = 8
+}
+
+typedef bit<48> mac_addr_t;
+typedef bit<32> ipv4_addr_t;
+const int NEXTHOP_ID_WIDTH = 14;
+typedef bit<(NEXTHOP_ID_WIDTH)> nexthop_id_t;
+
+const int MAC_TABLE_SIZE = 65536;
+const int VLAN_PORT_TABLE_SIZE = 1 << (7 + 12);
+const int NEXTHOP_TABLE_SIZE = 1 << NEXTHOP_ID_WIDTH;
+const int SUBVLAN_CHECK_TABLE_SIZE = 12288;
+
+const int IPV4_HOST_SIZE = 65536;
+const int IPV4_LPM_SIZE = 12288;
+const int IPV6_HOST_SIZE = 12000;
+const int IPV6_LPM_SIZE = 6000;
+
+/* We can use up to 8 different digest types */
+const bit<3> L2_LEARN_DIGEST = 1;
+
+/*************************************************************************
+ *********************** H E A D E R S *********************************
+ *************************************************************************/
+
+/* Define all the headers the program will recognize */
+/* The actual sets of headers processed by each gress can differ */
+
+/* Standard ethernet header */
+header ethernet_h {
+ mac_addr_t dst_addr;
+ mac_addr_t src_addr;
+}
+
+header vlan_tag_h {
+ bit<16> tpid;
+ bit<3> pcp;
+ bit<1> dei;
+ bit<12> vid;
+}
+
+header etherII_h {
+ ether_type_t ether_type;
+}
+
+header ipv4_t {
+ bit<4> version;
+ bit<4> ihl;
+ bit<8> diffserv;
+ bit<16> total_len;
+ bit<16> identification;
+ bit<3> flags;
+ bit<13> frag_offset;
+ bit<8> ttl;
+ ip_protocol_t protocol;
+ bit<16> hdr_checksum;
+ ipv4_addr_t src_addr;
+ ipv4_addr_t dst_addr;
+}
+
+header ipv4_options_t {
+ varbit<320> options;
+}
+
+header ipv6_t {
+ bit<4> version;
+ bit<8> traffic_class;
+ bit<20> flow_label;
+ bit<16> payload_len;
+ bit<8> next_hdr;
+ bit<8> hop_limit;
+ bit<128> src_addr;
+ bit<128> dst_addr;
+}
+
+header arp_h {
+ bit<16> hw_type;
+ ether_type_t proto_type;
+ bit<8> hw_addr_len;
+ bit<8> proto_addr_len;
+ arp_opcode_t opcode;
+}
+
+header arp_payload_h {
+ mac_addr_t src_hw_addr;
+ ipv4_addr_t src_proto_addr;
+ mac_addr_t dst_hw_addr;
+ ipv4_addr_t dst_proto_addr;
+}
+
+header icmp_h {
+ icmp_type_t msg_type;
+ bit<8> msg_code;
+ bit<16> checksum;
+}
+
+/*** Internal Headers ***/
+
+typedef bit<4> header_type_t; /* These fields can be coombined into one */
+typedef bit<4> header_info_t; /* 8-bit field as well. Exercise for the brave */
+
+const header_type_t HEADER_TYPE_BRIDGE = 0xB;
+const header_type_t HEADER_TYPE_MIRROR_INGRESS = 0xC;
+const header_type_t HEADER_TYPE_MIRROR_EGRESS = 0xD;
+const header_type_t HEADER_TYPE_RESUBMIT = 0xA;
+
+/*
+ * This is a common "preamble" header that must be present in all internal
+ * headers. The only time you do not need it is when you know that you are
+ * not going to have more than one internal header type ever
+ */
+#define INTERNAL_HEADER \
+ header_type_t header_type; \
+ header_info_t header_info
+
+
+header inthdr_h {
+ INTERNAL_HEADER;
+}
+
+/* Bridged metadata */
+header bridge_h {
+ INTERNAL_HEADER;
+
+ bit<7> pad0;
+ PortId_t ingress_port;
+
+ bit<3> pcp;
+ bit<1> dei;
+ bit<12> vid;
+}
+
+/*************************************************************************
+ ************** I N G R E S S P R O C E S S I N G *******************
+ *************************************************************************/
+
+ /*********************** H E A D E R S ************************/
+
+struct my_ingress_headers_t {
+ bridge_h bridge;
+ ethernet_h ethernet;
+ vlan_tag_h vlan_tag;
+ etherII_h etherII;
+ arp_h arp;
+ arp_payload_h arp_payload;
+ ipv4_t ipv4;
+ ipv4_options_t ipv4_options;
+ ipv6_t ipv6;
+ icmp_h icmp;
+}
+
+ /****** G L O B A L I N G R E S S M E T A D A T A *********/
+
+struct port_metadata_t {
+ bit<3> port_pcp;
+ bit<12> port_vid;
+ bit<9> l2_xid;
+}
+
+struct my_ingress_metadata_t {
+
+ bool ipv4_checksum_err;
+ ipv4_addr_t dst_ipv4;
+ port_metadata_t port_properties;
+
+ bit<3> pcp;
+ bit<1> dei;
+ bit<12> vid;
+ bit<12> dvid;
+ bit<9> mac_move; /* Should have the same size as PortId_t */
+ bit<1> is_static;
+ bit<1> smac_hit;
+ PortId_t ingress_port;
+}
+
+ /*********************** P A R S E R **************************/
+parser IngressParser(packet_in pkt,
+ /* User */
+ out my_ingress_headers_t hdr,
+ out my_ingress_metadata_t meta,
+ /* Intrinsic */
+ out ingress_intrinsic_metadata_t ig_intr_md)
+{
+
+ Checksum() ipv4_checksum;
+ /* This is a mandatory state, required by Tofino Architecture */
+ state start {
+ pkt.extract(ig_intr_md);
+ meta.port_properties = port_metadata_unpack<port_metadata_t>(pkt);
+ transition meta_init;
+ }
+
+ state meta_init {
+ meta.pcp = 0;
+ meta.dei = 0;
+ meta.vid = 0;
+ meta.dvid = 0;
+ meta.mac_move = 0;
+ meta.is_static = 0;
+ meta.smac_hit = 0;
+ meta.ingress_port = ig_intr_md.ingress_port;
+ meta.ipv4_checksum_err = false;
+ meta.dst_ipv4 = 0;
+ transition parse_ethernet;
+ }
+
+ state parse_ethernet {
+ pkt.extract(hdr.ethernet);
+ transition select(pkt.lookahead<bit<16>>()) {
+ (bit<16>)ether_type_t.TPID &&& 0xEFFF: parse_vlan_tag;
+ default: parse_etherII;
+ }
+ }
+
+ state parse_vlan_tag {
+ pkt.extract(hdr.vlan_tag);
+ meta.pcp = hdr.vlan_tag.pcp;
+ meta.dei = hdr.vlan_tag.dei;
+ meta.vid = hdr.vlan_tag.vid;
+ transition parse_etherII;
+ }
+
+ state parse_etherII {
+ pkt.extract(hdr.etherII);
+ transition select(hdr.etherII.ether_type) {
+ ether_type_t.IPV4 : parse_ipv4;
+ ether_type_t.IPV6 : parse_ipv6;
+ ether_type_t.ARP : parse_arp;
+ default: accept;
+ }
+ }
+
+ state parse_ipv4 {
+ pkt.extract(hdr.ipv4);
+ meta.dst_ipv4 = hdr.ipv4.dst_addr;
+ ipv4_checksum.add(hdr.ipv4);
+ transition select(hdr.ipv4.ihl) {
+ 0x5 : parse_ipv4_no_options;
+ 0x6 &&& 0xE : parse_ipv4_options;
+ 0x8 &&& 0x8 : parse_ipv4_options;
+ default: reject;
+ }
+ }
+
+ state parse_ipv4_options {
+ pkt.extract(
+ hdr.ipv4_options,
+ ((bit<32>)hdr.ipv4.ihl - 32w5) * 32);
+
+ ipv4_checksum.add(hdr.ipv4_options);
+ transition parse_ipv4_no_options;
+ }
+
+ state parse_ipv4_no_options {
+ meta.ipv4_checksum_err = ipv4_checksum.verify();
+
+ transition select(
+ hdr.ipv4.ihl,
+ hdr.ipv4.frag_offset,
+ hdr.ipv4.protocol) {
+ (5, 0, ip_protocol_t.ICMP) : parse_icmp;
+ default: accept;
+ }
+ }
+
+ state parse_icmp {
+ pkt.extract(hdr.icmp);
+ transition accept;
+ }
+
+ state parse_arp {
+ pkt.extract(hdr.arp);
+ transition select(hdr.arp.hw_type, hdr.arp.proto_type) {
+ (0x0001, ether_type_t.IPV4) : parse_arp_payload;
+ default: reject; // Currently the same as accept
+ }
+ }
+
+ state parse_arp_payload {
+ pkt.extract(hdr.arp_payload);
+ meta.dst_ipv4 = hdr.arp_payload.dst_proto_addr;
+ transition accept;
+ }
+
+ state parse_ipv6 {
+ pkt.extract(hdr.ipv6);
+ transition accept;
+ }
+}
+
+ /***************** M A T C H - A C T I O N *********************/
+
+control Ingress(
+ /* User */
+ inout my_ingress_headers_t hdr,
+ inout my_ingress_metadata_t meta,
+ /* Intrinsic */
+ in ingress_intrinsic_metadata_t ig_intr_md,
+ in ingress_intrinsic_metadata_from_parser_t ig_prsr_md,
+ inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md,
+ inout ingress_intrinsic_metadata_for_tm_t ig_tm_md)
+{
+
+ nexthop_id_t nexthop_id = 0;
+ PortId_t dst_sub_port = 0;
+ bit<16> src_sid = 0;
+ mac_addr_t dst_mac = 0;
+ bit<8> ttl_dec = 0;
+ bit<1> is_to_l3 = 0;
+ bit<1> is_same_vlan = 0;
+
+/************************ Common Action *************************/
+ action drop() {
+ ig_dprsr_md.drop_ctl = 1;
+ }
+
+ action send(PortId_t port) {
+ ig_tm_md.ucast_egress_port = port;
+ }
+/************************* Port VLAN Table *************************/
+
+ action vlan_port_miss() { }
+
+ action get_sid_vid(bit<16> superid, bit<12> subid){
+ meta.vid = subid;
+ src_sid = superid;
+ }
+
+ table vlan_port {
+ key = { ig_intr_md.ingress_port : exact; }
+ actions = {
+ get_sid_vid;
+ vlan_port_miss;
+ }
+ size = MAC_TABLE_SIZE;
+ const default_aciotn = vlan_port_miss();
+ }
+
+/*************************** Smac **********************************/
+ action smac_hit(PortId_t port, bit<1> is_static) {
+ meta.mac_move = ig_intr_md.ingress_port ^ port;
+ meta.smac_hit = 1;
+ meta.is_static = is_static;
+ }
+
+ action smac_miss() { }
+
+ action smac_drop() {
+ drop(); exit;
+ }
+
+ //@idletime_precision(3)
+ table smac {
+ key = {
+ meta.vid : exact;
+ hdr.ethernet.src_addr : exact;
+ }
+ actions = {
+ smac_hit; smac_miss; smac_drop;
+ }
+ size = MAC_TABLE_SIZE;
+ const default_action = smac_miss();
+ //idle_timeout = true;
+ }
+
+/*************************** Smac Result **************************/
+ action mac_learn_notify() {
+ ig_dprsr_md.digest_type = L2_LEARN_DIGEST;
+ }
+
+ table smac_results {
+ key = {
+ meta.mac_move : ternary;
+ meta.is_static : ternary;
+ meta.smac_hit : ternary;
+ }
+ actions = {
+ mac_learn_notify; NoAction; smac_drop;
+ }
+ const entries = {
+ ( _, _, 0) : mac_learn_notify();
+ ( 0, _, 1) : NoAction();
+ ( _, 0, 1) : mac_learn_notify();
+ ( _, 1, 1) : smac_drop();
+ }
+ }
+
+/************************** Dmac ****************************/
+
+ action change_to_l3(bit<1> to_l3) {
+ is_to_l3 = to_l3;
+ }
+
+ action dmac_unicast(PortId_t port) {
+ send(port);
+ }
+
+ action dmac_miss() {
+ ig_tm_md.mcast_grp_a = (MulticastGroupId_t)src_sid;
+ ig_tm_md.rid = src_sid;
+ /* Set the exclusion id here, since parser can't acces ig_tm_md */
+ ig_tm_md.level2_exclusion_id = meta.port_properties.l2_xid;
+ }
+
+ action dmac_sub_multicast(MulticastGroupId_t mcast_grp) {
+ ig_tm_md.mcast_grp_a = mcast_grp;
+ ig_tm_md.rid = (bit<16>)meta.vid;
+ /* Set the exclusion id here, since parser can't acces ig_tm_md */
+ ig_tm_md.level2_exclusion_id = meta.port_properties.l2_xid;
+ }
+
+ action dmac_super_multicast(MulticastGroupId_t mcast_grp) {
+ ig_tm_md.mcast_grp_a = mcast_grp;
+ ig_tm_md.rid = src_sid;
+ /* Set the exclusion id here, since parser can't acces ig_tm_md */
+ ig_tm_md.level2_exclusion_id = meta.port_properties.l2_xid;
+ }
+
+ action dmac_drop() {
+ drop();
+ exit;
+ }
+
+ table dmac {
+ key = {
+ meta.vid : exact;
+ hdr.ethernet.dst_addr : exact;
+ }
+ actions = {
+ dmac_unicast; dmac_miss; dmac_sub_multicast; dmac_super_multicast; dmac_drop; change_to_l3;
+ }
+ size = MAC_TABLE_SIZE;
+ default_action = dmac_miss();
+ }
+
+
+/**************************** Ipv4/Ipv6 Table*******************************/
+ action set_nexthop(nexthop_id_t id) {
+ nexthop_id = id;
+ }
+
+ table ipv4_host {
+ key = {
+ hdr.ipv4.dst_addr : exact;
+ }
+ actions = {
+ set_nexthop;
+ @defaultonly NoAction;
+ }
+ const default_action = NoAction();
+ size = IPV4_HOST_SIZE;
+ }
+
+ table ipv4_lpm {
+ key = {
+ hdr.ipv4.dst_addr : lpm;
+ }
+ actions = { set_nexthop; }
+ default_action = set_nexthop(0);
+ size = IPV4_LPM_SIZE;
+ }
+
+ table ipv6_host {
+ key = { hdr.ipv6.dst_addr : exact; }
+ actions = {
+ set_nexthop;
+ @defaultonly NoAction;
+ }
+ const default_action = NoAction();
+ size = IPV6_HOST_SIZE;
+ }
+
+ table ipv6_lpm {
+ key = { hdr.ipv6.dst_addr : lpm; }
+ actions = { set_nexthop; }
+
+ default_action = set_nexthop(0);
+ size = IPV6_LPM_SIZE;
+ }
+
+
+/******************************** Nexthop ***********************************/
+
+
+ action l3_switch(PortId_t port, mac_addr_t new_mac_da, mac_addr_t new_mac_sa) {
+ hdr.ethernet.dst_addr = new_mac_da;
+ hdr.ethernet.src_addr = new_mac_sa;
+ ttl_dec = 1;
+ send(port);
+ }
+
+
+ table nexthop {
+ key = { nexthop_id : exact; }
+ actions = { send; drop; l3_switch; }
+ default_action = send(64);
+ size = NEXTHOP_TABLE_SIZE;
+ }
+
+/************************** SubVlan_check table *************************/
+
+
+ action subvlan_send(PortId_t port){
+ dst_sub_port = port;
+ send(port);
+ }
+
+ table subvlan_check{
+ key = {
+ meta.dst_ipv4:exact;
+ meta.vid: exact;
+ }
+ actions = {
+ subvlan_send;
+ change_to_l3;
+ }
+ default_action = change_to_l3(1);
+ size = SUBVLAN_CHECK_TABLE_SIZE;
+ }
+
+
+/************************** ARP Response ********************************/
+ action send_back() {
+ ig_tm_md.ucast_egress_port = ig_intr_md.ingress_port;
+ }
+
+ action send_arp_reply(mac_addr_t gate_mac) {
+ hdr.ethernet.dst_addr = hdr.arp_payload.src_hw_addr;
+ hdr.ethernet.src_addr = gate_mac;
+ hdr.arp.opcode = arp_opcode_t.REPLY;
+
+ hdr.arp_payload.dst_hw_addr = hdr.arp_payload.src_hw_addr;
+ hdr.arp_payload.dst_proto_addr = hdr.arp_payload.src_proto_addr;
+ hdr.arp_payload.src_hw_addr = gate_mac;
+ hdr.arp_payload.src_proto_addr = meta.dst_ipv4;
+
+ send_back();
+ }
+
+ table arp_reply {
+ key = {
+ //hdr.arp.isValid() : exact;
+ //hdr.arp_payload.isValid() : exact;
+ hdr.arp.opcode : exact;
+ }
+ actions = {
+ send_arp_reply;
+ drop;
+ }
+ default_action = drop();
+ }
+
+/****************************** Apply *******************************/
+
+ apply {
+
+ /* Assign Port-based VLAN to untagged/priority-tagged packets */
+ if (meta.vid == 0) {
+ meta.vid = meta.port_properties.port_vid;
+ }
+
+ if (!hdr.vlan_tag.isValid()) {
+ meta.pcp = meta.port_properties.port_pcp;
+ }
+
+ vlan_port.apply();
+ smac.apply();
+ smac_results.apply();
+ switch (dmac.apply().action_run) {
+ dmac_unicast: {
+ if (ig_intr_md.ingress_port ==
+ ig_tm_md.ucast_egress_port) {
+ drop();
+ }
+ }
+ }
+
+ subvlan_check.apply();
+
+ if(is_to_l3 == 1) {
+ if(hdr.arp.isValid() && hdr.arp_payload.isValid()){
+ arp_reply.apply();
+ }
+ else {
+ if (hdr.ipv4.isValid()) {
+ if (meta.ipv4_checksum_err == false) {
+ if (!ipv4_host.apply().hit) {
+ ipv4_lpm.apply();
+ }
+ }
+ }
+ else if (hdr.ipv6.isValid()) {
+ if (hdr.ipv6.hop_limit > 1) {
+ if (!ipv6_host.apply().hit) {
+ ipv6_lpm.apply();
+ }
+ }
+ }
+ nexthop.apply();
+ if (hdr.ipv4.isValid()) {
+ hdr.ipv4.ttl = hdr.ipv4.ttl |-| ttl_dec;
+ }
+ else if (hdr.ipv6.isValid()) {
+ hdr.ipv6.hop_limit = hdr.ipv6.hop_limit |-| ttl_dec;
+ }
+ }
+ }
+
+
+ /* Bridge metadata to the egress pipeline */
+ hdr.bridge.setValid();
+ hdr.bridge.header_type = HEADER_TYPE_BRIDGE;
+ hdr.bridge.header_info = 0; /* Ignore */
+ hdr.bridge.ingress_port = ig_intr_md.ingress_port;
+ hdr.bridge.pcp = meta.pcp;
+ hdr.bridge.dei = meta.dei;
+ hdr.bridge.vid = meta.vid;
+ }
+}
+
+ /********************* D E P A R S E R ************************/
+
+/* This struct is needed for proper digest receive API generation */
+struct l2_digest_t {
+ bit<12> vid;
+ bit<48> src_mac;
+ bit<9> ingress_port;
+ bit<9> mac_move;
+ bit<1> is_static;
+ bit<1> smac_hit;
+}
+
+control IngressDeparser(packet_out pkt,
+ /* User */
+ inout my_ingress_headers_t hdr,
+ in my_ingress_metadata_t meta,
+ /* Intrinsic */
+ in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md)
+{
+ Checksum() ipv4_checksum;
+ Digest <l2_digest_t>() l2_digest;
+
+ apply {
+ if (ig_dprsr_md.digest_type == L2_LEARN_DIGEST) {
+ l2_digest.pack({
+ meta.vid,
+ hdr.ethernet.src_addr,
+ meta.ingress_port,
+ meta.mac_move,
+ meta.is_static,
+ meta.smac_hit });
+ }
+ hdr.ipv4.hdr_checksum = ipv4_checksum.update({
+ hdr.ipv4.version,
+ hdr.ipv4.ihl,
+ hdr.ipv4.diffserv,
+ hdr.ipv4.total_len,
+ hdr.ipv4.identification,
+ hdr.ipv4.flags,
+ hdr.ipv4.frag_offset,
+ hdr.ipv4.ttl,
+ hdr.ipv4.protocol,
+ hdr.ipv4.src_addr,
+ hdr.ipv4.dst_addr,
+ hdr.ipv4_options.options
+ });
+ pkt.emit(hdr);
+ }
+}
+
+
+/*************************************************************************
+ **************** E G R E S S P R O C E S S I N G *******************
+ *************************************************************************/
+
+ /*********************** H E A D E R S ************************/
+
+struct my_egress_headers_t {
+ ethernet_h ethernet;
+ vlan_tag_h vlan_tag;
+ etherII_h etherII;
+}
+
+ /******** G L O B A L E G R E S S M E T A D A T A *********/
+
+struct my_egress_metadata_t {
+ bridge_h bridge;
+
+ PortId_t ingress_port;
+ bit<3> pcp;
+ bit<1> dei;
+ bit<12> vid;
+}
+
+ /*********************** P A R S E R **************************/
+
+parser EgressParser(packet_in pkt,
+ /* User */
+ out my_egress_headers_t hdr,
+ out my_egress_metadata_t meta,
+ /* Intrinsic */
+ out egress_intrinsic_metadata_t eg_intr_md)
+{
+ inthdr_h inthdr;
+
+ /* This is a mandatory state, required by Tofino Architecture */
+ state start {
+ pkt.extract(eg_intr_md);
+ inthdr = pkt.lookahead<inthdr_h>();
+ transition select(inthdr.header_type, inthdr.header_info) {
+ ( HEADER_TYPE_BRIDGE, _ ) : parse_bridge;
+ default : reject;
+ }
+ }
+
+ state parse_bridge {
+ pkt.extract(meta.bridge);
+ meta.ingress_port = meta.bridge.ingress_port;
+ meta.pcp = meta.bridge.pcp;
+ meta.dei = meta.bridge.dei;
+ meta.vid = meta.bridge.vid;
+ transition parse_ethernet;
+ }
+
+ state parse_ethernet {
+ pkt.extract(hdr.ethernet);
+ transition select(pkt.lookahead<bit<16>>()) {
+ (bit<16>)ether_type_t.TPID &&& 0xEFFF: parse_vlan_tag;
+ default: parse_etherII;
+ }
+ }
+
+ state parse_vlan_tag {
+ pkt.extract(hdr.vlan_tag);
+ transition parse_etherII;
+ }
+
+ state parse_etherII {
+ pkt.extract(hdr.etherII);
+ transition accept;
+ }
+}
+
+ /***************** M A T C H - A C T I O N *********************/
+
+/* This program is written in a modular fashion using multiple different
+ * implementations of the Egress control. You can try to see which ones are
+ * more efficient
+ */
+
+control Egress(
+ /* User */
+ inout my_egress_headers_t hdr,
+ inout my_egress_metadata_t meta,
+ /* Intrinsic */
+ in egress_intrinsic_metadata_t eg_intr_md,
+ in egress_intrinsic_metadata_from_parser_t eg_prsr_md,
+ inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md,
+ inout egress_intrinsic_metadata_for_output_port_t eg_oport_md)
+{
+ apply{
+ }
+}
+
+ /********************* D E P A R S E R ************************/
+
+control EgressDeparser(packet_out pkt,
+ /* User */
+ inout my_egress_headers_t hdr,
+ in my_egress_metadata_t meta,
+ /* Intrinsic */
+ in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md)
+{
+ apply {
+ pkt.emit(hdr);
+ }
+}
+
+
+/************ F I N A L P A C K A G E ******************************/
+Pipeline(
+ IngressParser(),
+ Ingress(),
+ IngressDeparser(),
+ EgressParser(),
+ Egress(),
+ EgressDeparser()
+) pipe;
+
+Switch(pipe) main;
diff --git a/vlan_aggregation/ptf-tests/test.py b/vlan_aggregation/ptf-tests/test.py
new file mode 100644
index 0000000..1f8c2c2
--- /dev/null
+++ b/vlan_aggregation/ptf-tests/test.py
@@ -0,0 +1,1140 @@
+"""
+Simple PTF test for vlan aggregation
+"""
+
+######### STANDARD MODULE IMPORTS ########
+import logging
+import grpc
+import pdb
+
+######### PTF modules for BFRuntime Client Library APIs #######
+import ptf
+from ptf.testutils import *
+from bfruntime_client_base_tests import BfRuntimeTest
+import bfrt_grpc.bfruntime_pb2 as bfruntime_pb2
+import bfrt_grpc.client as gc
+import bfrt_grpc.info_parse as info_parse
+
+########## Basic Initialization ############
+class BaseProgramTest(BfRuntimeTest):
+ # The setUp() method is used to prepare the test fixture. Typically
+ # you would use it to establich connection to the gRPC Server
+ #
+ # You can also put the initial device configuration there. However,
+ # if during this process an error is encountered, it will be considered
+ # as a test error (meaning the test is incorrect),
+ # rather than a test failure
+ #
+ # Here is the stuff we set up that is ready to use
+ # client_id
+ # p4_name
+ # bfrt_info
+ # dev
+ # dev_tgt
+ # allports
+ # tables -- the list of tables
+ # Individual tables of the program with short names
+ # ipv4_host
+ # ipv4_lpm
+ # nexthop
+ def setUp(self):
+ self.client_id = 0
+ self.p4_name = "vlan_aggregation"
+ self.dev = 0
+ self.dev_tgt = gc.Target(self.dev, pipe_id=0xFFFF)
+
+ print("\n")
+ print("Test Setup")
+ print("==========")
+
+ BfRuntimeTest.setUp(self, self.client_id, self.p4_name)
+ self.bfrt_info = self.interface.bfrt_info_get(self.p4_name)
+
+ print(" Connected to Device: {}, Program: {}, ClientId: {}".format(
+ self.dev, self.p4_name, self.client_id))
+
+ # Since this class is not a test per se, we can use the setup method
+ # for common setup. For example, we can have our tables and annotations
+ # ready
+ self.vlan_port = self.bfrt_info.table_get("Ingress.vlan_port")
+
+ self.smac = self.bfrt_info.table_get("Ingress.smac")
+ self.smac.info.key_field_annotation_add("hdr.ethernet.src_addr", "mac")
+
+ self.smac_results = self.bfrt_info.table_get("Ingress.smac_results")
+
+ self.dmac = self.bfrt_info.table_get("Ingress.dmac")
+ self.dmac.info.key_field_annotation_add("hdr.ethernet.dst_addr", "mac")
+
+ self.subvlan_check = self.bfrt_info.table_get("Ingress.subvlan_check")
+ self.subvlan_check.info.key_field_annotation_add("meta.dst_ipv4", "ipv4")
+
+ self.arp_reply = self.bfrt_info.table_get("Ingress.arp_reply")
+ self.arp_reply.info.data_field_annotation_add("gate_mac", "Ingress.send_arp_reply", "mac")
+
+ self.ipv4_host = self.bfrt_info.table_get("Ingress.ipv4_host")
+ self.ipv4_host.info.key_field_annotation_add("hdr.ipv4.dst_addr", "ipv4")
+
+ self.ipv4_lpm = self.bfrt_info.table_get("Ingress.ipv4_lpm")
+ self.ipv4_lpm.info.key_field_annotation_add("hdr.ipv4.dst_addr", "ipv4")
+
+ self.nexthop = self.bfrt_info.table_get("Ingress.nexthop")
+ self.nexthop.info.data_field_annotation_add("new_mac_da", "Ingress.l3_switch", "mac")
+ self.nexthop.info.data_field_annotation_add("new_mac_sa", "Ingress.l3_switch", "mac")
+
+ self.tables = [ self.vlan_port, self.smac, self.smac_results, self.dmac, self.subvlan_check, self.arp_reply, self.ipv4_host, self.ipv4_lpm, self.nexthop ]
+
+ # Create a list of all ports available on the device
+ self.swports = []
+ for (device, port, ifname) in ptf.config['interfaces']:
+ self.swports.append(port)
+ self.swports.sort()
+
+ # Optional, but highly recommended
+ self.cleanUp()
+
+ # Use Cleanup Method to clear the tables before and after the test starts
+ # (the latter is done as a part of tearDown()
+ def cleanUp(self):
+ print("\n")
+ print("Table Cleanup:")
+ print("==============")
+
+ try:
+ for t in self.tables:
+ print(" Clearing Table {}".format(t.info.name_get()))
+ keys = []
+ for (d, k) in t.entry_get(self.dev_tgt):
+ if k is not None:
+ keys.append(k)
+ t.entry_del(self.dev_tgt, keys)
+ # Not all tables support default entry
+ try:
+ t.default_entry_reset(self.dev_tgt)
+ except:
+ pass
+ except Exception as e:
+ print("Error cleaning up: {}".format(e))
+
+ # Use tearDown() method to return the DUT to the initial state by cleaning
+ # all the configuration and clearing up the connection
+ def tearDown(self):
+ print("\n")
+ print("Test TearDown:")
+ print("==============")
+
+ self.cleanUp()
+
+ # Call the Parent tearDown
+ BfRuntimeTest.tearDown(self)
+
+#
+# Individual tests can now be subclassed from BaseProgramTest
+#
+
+############################################################################
+################# I N D I V I D U A L T E S T S #########################
+############################################################################
+class ArpReply(BaseProgramTest):
+ def runTest(self):
+ #vlan-port->smac->smac_results->dmac->arp_reply
+ ingress_port = test_param_get("ingress_port", 1)
+ superid = test_param_get('superid', 1)
+ subid = test_param_get('subid', 1)
+ mac_src = test_param_get("mac_src", "00:00:01:00:00:01") #192.168.10.1's mac
+ is_static = test_param_get('is_static', 1)
+ is_to_l3 = test_param_get('is_to_l3', 1)
+ mac_dst = test_param_get("mac_dst", "ff:ff:ff:ff:ff:ff") #L3 gateway mac
+ gate_mac = test_param_get("gate_mac", "01:02:03:04:05:06") #L3 gateway mac
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.10.16")
+ is_valid = test_param_get("is_valid", True)
+ is_opcode = test_param_get("is_opcode", 1)
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in vlan_port: vlan_port --> get_sid_vid(superid, subid)
+ #
+ key = self.vlan_port.make_key([
+ gc.KeyTuple('ig_intr_md.ingress_port', ingress_port)])
+
+ data = self.vlan_port.make_data(
+ [gc.DataTuple('superid',superid),
+ gc.DataTuple('subid',subid)],
+ "Ingress.get_sid_vid")
+
+ self.vlan_port.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to vlan_port: ingress_port{} --> get_sid_vid({},{})".format(
+ ingress_port, superid, subid))
+
+ #
+ # Program an entry in smac: subid, mac_src --> smac_hit(ingress_port, is_static)
+ #
+ key = self.smac.make_key([gc.KeyTuple('meta.vid', subid),
+ gc.KeyTuple('hdr.ethernet.src_addr', mac_src)])
+
+ data = self.smac.make_data([gc.DataTuple('port', ingress_port), gc.DataTuple('is_static',is_static)],
+ "Ingress.smac_hit")
+
+ self.smac.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry smac: meta.vid:{} hdr.ethernet.src_addr{} --> smac_hit({},{})".format(
+ subid, mac_src, ingress_port, is_static))
+
+ #
+ # Program an entry in dmac: subid, mac_dst --> change_to_l3(to_l3)
+ #
+ key = self.dmac.make_key([
+ gc.KeyTuple('meta.vid', subid),
+ gc.KeyTuple('hdr.ethernet.dst_addr', mac_dst)])
+
+ data = self.dmac.make_data(
+ [gc.DataTuple('to_l3', is_to_l3)],
+ "Ingress.change_to_l3")
+
+ self.dmac.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry smac: meta.vid:{} hdr.ethernet.dst_addr{} --> change_to_l3({})".format(
+ subid, mac_dst,is_static))
+
+ #
+ # Program an entry in arp_reply: hdr.arp.isValid(),hdr.arp_payload.isValid(),hdr.arp.opcode --> send_arp_reply(gate_mac)
+ #
+ key = self.arp_reply.make_key([
+ #gc.KeyTuple('hdr.arp.isValid()', is_valid),
+ #gc.KeyTuple('hdr.arp_payload.isValid()', is_valid),
+ gc.KeyTuple('hdr.arp.opcode', is_opcode)])
+
+ data = self.arp_reply.make_data(
+ [gc.DataTuple('gate_mac', gate_mac)],
+ "Ingress.send_arp_reply")
+
+ self.arp_reply.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry in arp_reply: arp_reply: --> change_to_l3({})".format(is_to_l3))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+ send_pkt = simple_arp_packet(ip_tgt=ipv4_dst, pktlen=100)
+ send_packet(self, ingress_port, send_pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the packet to be forwarded to port {}"
+ .format(ingress_port))
+
+ exp_pkt = copy.deepcopy(send_pkt)
+ exp_pkt[Ether].dst = send_pkt[ARP].hwsrc
+ exp_pkt[Ether].src = gate_mac
+ exp_pkt[ARP].op = 2
+ exp_pkt[ARP].hwsrc = gate_mac
+ exp_pkt[ARP].psrc = ipv4_dst
+ exp_pkt[ARP].hwdst = send_pkt[ARP].hwsrc
+ exp_pkt[ARP].pdst = send_pkt[ARP].psrc
+
+ verify_packet(self, exp_pkt, ingress_port)
+ print(" Packet received of port {}".format(ingress_port))
+
+
+
+class SameSubVLANSend(BaseProgramTest):
+ def runTest(self):
+ #vlan-port->smac->smac_results->dmac->subvlan_check
+ port_1 = test_param_get("port_1", 1)
+ port_2 = test_param_get("port_2", 2)
+ superid = test_param_get('superid', 1)
+ subid_1 = test_param_get('subid_1', 1)
+ subid_2 = test_param_get('subid_2', 1)
+ mac_src = test_param_get("mac_src", "00:00:01:00:00:01") #192.168.10.1's mac
+ is_static = test_param_get('is_static', 1)
+ mac_dst = test_param_get("mac_dst", "00:00:02:00:00:02") #192.168.10.2's mac
+ #is_to_l3 = test_param_get('is_to_l3', 1)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.10.2")
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in vlan_port: vlan_port --> get_sid_vid(superid, src_subid)
+ #
+ key_list = [
+ self.vlan_port.make_key([
+ gc.KeyTuple('ig_intr_md.ingress_port', port_1)]),
+ self.vlan_port.make_key([
+ gc.KeyTuple('ig_intr_md.ingress_port', port_2)])
+ ]
+
+ data_list = [
+ self.vlan_port.make_data([gc.DataTuple('superid',superid), gc.DataTuple('subid',subid_1)], "Ingress.get_sid_vid"),
+ self.vlan_port.make_data([gc.DataTuple('superid',superid), gc.DataTuple('subid',subid_2)], "Ingress.get_sid_vid")
+ ]
+
+ self.vlan_port.entry_add(self.dev_tgt, key_list, data_list);
+ print("Add vlan_port: ingress_port{} --> get_sid_vid({},{})".format(port_1, superid, subid_1))
+ print("Add vlan_port: ingress_port{} --> get_sid_vid({},{})".format(port_2, superid, subid_2))
+
+ #
+ # Program an entry in smac: subid, mac_src --> smac_hit(ingress_port, is_static)
+ #
+ key_list = [
+ self.smac.make_key([gc.KeyTuple('meta.vid', subid_1), gc.KeyTuple('hdr.ethernet.src_addr', mac_src)]),
+ self.smac.make_key([gc.KeyTuple('meta.vid', subid_2), gc.KeyTuple('hdr.ethernet.src_addr', mac_dst)])
+ ]
+
+ data_list = [
+ self.smac.make_data([gc.DataTuple('port', port_1), gc.DataTuple('is_static',is_static)],"Ingress.smac_hit"),
+ self.smac.make_data([gc.DataTuple('port', port_2), gc.DataTuple('is_static',is_static)],"Ingress.smac_hit")
+ ]
+
+ self.smac.entry_add(self.dev_tgt, key_list, data_list);
+ print("Add smac: subid:{}, mac_src:{} --> get_sid_vid({},{})".format(
+ subid_1, mac_src, port_1, is_static))
+ print("Add smac: subid:{}, mac_src:{} --> get_sid_vid({},{})".format(
+ subid_2, mac_dst, port_2, is_static))
+
+ #
+ # Program an entry in subvlan_check: meta.dst_ipv4 --> subvlan_send(subid, port)
+ #
+ key_list = [
+ self.subvlan_check.make_key([gc.KeyTuple('meta.dst_ipv4', ipv4_dst), gc.KeyTuple('meta.vid', subid_2)])
+ ]
+
+ data_list = [
+ self.subvlan_check.make_data([gc.DataTuple('port',port_2)],"Ingress.subvlan_send")
+ ]
+ self.subvlan_check.entry_add(self.dev_tgt, key_list, data_list);
+ print("Add subvlan_check: meta.dst_ipv4:{} --> subvlan_send({},{})".format(
+ ipv4_dst, subid_2, port_2))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, port_1))
+ pkt = simple_tcp_packet(eth_dst=mac_dst,
+ eth_src=mac_src,
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, port_1, pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the packet to be forwarded to port {}"
+ .format(port_2))
+ verify_packet(self, pkt, port_2)
+ print(" Packet received of port {}".format(port_2))
+
+class DiffSubVLANSend(BaseProgramTest):
+ def runTest(self):
+ #vlan_port->smac->smac_results->subvlan_check->ipv4_host->nexthop
+ #the entries in smac_results is static
+ port_1 = test_param_get("port_1", 1)
+ port_2 = test_param_get("port_2", 3)
+ superid = test_param_get('superid', 1)
+ subid_1 = test_param_get('subid_1', 1)
+ subid_2 = test_param_get('subid_2', 2)
+ mac_src = test_param_get("mac_src", "00:00:01:00:00:01") #192.168.10.1's mac
+ is_static = test_param_get('is_static', 1)
+ mac_dst = test_param_get("mac_dst", "00:00:03:00:00:03") #L3 gateway mac
+ #is_to_l3 = test_param_get('is_to_l3', 1)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.10.3")
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in vlan_port: vlan_port --> get_sid_vid(superid, src_subid)
+ #
+ key_list = [
+ self.vlan_port.make_key([
+ gc.KeyTuple('ig_intr_md.ingress_port', port_1)]),
+ self.vlan_port.make_key([
+ gc.KeyTuple('ig_intr_md.ingress_port', port_2)])
+ ]
+
+ data_list = [
+ self.vlan_port.make_data([gc.DataTuple('superid',superid), gc.DataTuple('subid',subid_1)], "Ingress.get_sid_vid"),
+ self.vlan_port.make_data([gc.DataTuple('superid',superid), gc.DataTuple('subid',subid_2)], "Ingress.get_sid_vid")
+ ]
+
+ self.vlan_port.entry_add(self.dev_tgt, key_list, data_list);
+ print("Add vlan_port: ingress_port{} --> get_sid_vid({},{})".format(
+ port_1, superid, subid_1))
+ print("Add vlan_port: ingress_port{} --> get_sid_vid({},{})".format(
+ port_2, superid, subid_2))
+
+ #
+ # Program an entry in smac: subid, mac_src --> smac_hit(ingress_port, is_static)
+ #
+ key_list = [
+ self.smac.make_key([gc.KeyTuple('meta.vid', subid_1), gc.KeyTuple('hdr.ethernet.src_addr', mac_src)]),
+ self.smac.make_key([gc.KeyTuple('meta.vid', subid_2), gc.KeyTuple('hdr.ethernet.src_addr', mac_dst)])
+ ]
+
+ data_list = [
+ self.smac.make_data([gc.DataTuple('port', port_1), gc.DataTuple('is_static',is_static)],"Ingress.smac_hit"),
+ self.smac.make_data([gc.DataTuple('port', port_2), gc.DataTuple('is_static',is_static)],"Ingress.smac_hit")
+ ]
+
+ self.smac.entry_add(self.dev_tgt, key_list, data_list);
+ print("Add smac: subid:{}, mac_src:{} --> get_sid_vid({},{})".format(
+ subid_1, mac_src, port_1, is_static))
+ print("Add smac: subid:{}, mac_src:{} --> get_sid_vid({},{})".format(
+ subid_2, mac_dst, port_2, is_static))
+
+ #
+ # Program an entry in subvlan_check: meta.dst_ipv4 --> subvlan_send(subid, port)
+ #
+ key_list = [
+ self.subvlan_check.make_key([gc.KeyTuple('meta.dst_ipv4', ipv4_dst),gc.KeyTuple('meta.vid', subid_2)])
+ ]
+
+ data_list = [
+ self.subvlan_check.make_data([gc.DataTuple('port',port_2)],"Ingress.subvlan_send")
+ ]
+ self.subvlan_check.entry_add(self.dev_tgt, key_list, data_list);
+ print("Add subvlan_check: meta.dst_ipv4:{} --> subvlan_send({},{})".format(
+ ipv4_dst, subid_2, port_2))
+
+ #
+ # Program an entry in ipv4_host: ipv4_dst --> set_nexthop(nexthop_id)
+ #
+ key = self.ipv4_host.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr', ipv4_dst)])
+
+ data = self.ipv4_host.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+
+ self.ipv4_host.entry_add(self.dev_tgt, [key], [data])
+ print(" Added an entry to ipv4_host: {} --> set_nexthop({})".
+ format(ipv4_dst, nexthop_id))
+
+ #
+ # Program an entry in nexthop: nexthop_id --> send(egress_port)
+ #
+ key = self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+
+ data = self.nexthop.make_data([
+ gc.DataTuple('port', port_2)], "Ingress.send")
+
+ self.nexthop.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to nexthop: {} --> send({})".format(
+ nexthop_id, port_2))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, port_1))
+ pkt = simple_tcp_packet(eth_dst="00:00:03:00:00:03",
+ eth_src='00:00:01:00:00:01',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, port_1, pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the packet to be forwarded to port {}"
+ .format(port_2))
+ verify_packet(self, pkt, port_2)
+ print(" Packet received of port {}".format(port_2))
+
+
+class DiffSuperVLANSend(BaseProgramTest):
+ def runTest(self):
+ #vlan_port->smac->smac_results->dmac->ipv4_host->nexthop
+ #the entries in smac_results is static
+ ingress_port = test_param_get("ingress_port", 0)
+ superid = test_param_get('superid', 1)
+ subid = test_param_get('subid', 1)
+ mac_src = test_param_get("mac_src", "00:00:01:00:00:01") #192.168.10.1's mac
+ is_static = test_param_get('is_static', 1)
+ mac_dst = test_param_get("mac_dst", "01:02:03:04:05:06") #L3 gateway mac
+ is_to_l3 = test_param_get('is_to_l3', 1)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.3.8")
+ egress_port = test_param_get("egress_port", 4)
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in vlan_port: vlan_port --> get_sid_vid(superid, subid)
+ #
+ key = self.vlan_port.make_key([
+ gc.KeyTuple('ig_intr_md.ingress_port', ingress_port)])
+
+ data = self.vlan_port.make_data(
+ [gc.DataTuple('superid',superid),
+ gc.DataTuple('subid',subid)],
+ "Ingress.get_sid_vid")
+
+ self.vlan_port.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to vlan_port: ingress_port{} --> get_sid_vid({},{})".format(
+ ingress_port, superid, subid))
+
+ #
+ # Program an entry in smac: subid, mac_src --> smac_hit(ingress_port, is_static)
+ #
+ key = self.smac.make_key([
+ gc.KeyTuple('meta.vid', subid),
+ gc.KeyTuple('hdr.ethernet.src_addr', mac_src)])
+
+ data = self.smac.make_data(
+ [gc.DataTuple('port', ingress_port), gc.DataTuple('is_static',is_static)],"Ingress.smac_hit")
+
+ self.smac.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry smac: meta.vid:{} hdr.ethernet.src_addr{} --> smac_hit({},{})".format(
+ subid, mac_src, ingress_port, is_static))
+
+ #
+ # Program an entry in dmac: subid, mac_dst --> change_to_l3(to_l3)
+ #
+ key = self.dmac.make_key([
+ gc.KeyTuple('meta.vid', subid),
+ gc.KeyTuple('hdr.ethernet.dst_addr', mac_dst)])
+
+ data = self.dmac.make_data([gc.DataTuple('to_l3', is_to_l3)], "Ingress.change_to_l3")
+
+ self.dmac.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry smac: meta.vid:{} hdr.ethernet.dst_addr{} --> change_to_l3({})".format(
+ subid, mac_dst,is_static))
+
+ #
+ # Program an entry in ipv4_host: ipv4_dst --> set_nexthop(nexthop_id)
+ #
+ key = self.ipv4_host.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr', ipv4_dst)])
+
+ data = self.ipv4_host.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+
+ self.ipv4_host.entry_add(self.dev_tgt, [key], [data])
+ print(" Added an entry to ipv4_host: {} --> set_nexthop({})".
+ format(ipv4_dst, nexthop_id))
+
+ #
+ # Program an entry in nexthop: nexthop_id --> send(egress_port)
+ #
+ key = self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+
+ data = self.nexthop.make_data([
+ gc.DataTuple('port', egress_port)], "Ingress.send")
+
+ self.nexthop.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to nexthop: {} --> send({})".format(
+ nexthop_id, egress_port))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+ pkt = simple_tcp_packet(eth_dst="01:02:03:04:05:06",
+ eth_src='00:00:01:00:00:01',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, ingress_port, pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the packet to be forwarded to port {}"
+ .format(egress_port))
+ verify_packet(self, pkt, egress_port)
+ print(" Packet received of port {}".format(egress_port))
+
+class HostSend(BaseProgramTest):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ egress_port = test_param_get("egress_port", 4)
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in nexthop: nexthop_id --> send(egress_port)
+ #
+ key = self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+
+ data = self.nexthop.make_data([
+ gc.DataTuple('port', egress_port)], "Ingress.send")
+
+ self.nexthop.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to nexthop: {} --> send({})".format(
+ nexthop_id, egress_port))
+
+ #
+ # Program an entry in ipv4_host: ipv4_dst --> set_nexthop(nexthop_id)
+ #
+ key = self.ipv4_host.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr', ipv4_dst)])
+
+ data = self.ipv4_host.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+
+ self.ipv4_host.entry_add(self.dev_tgt, [key], [data])
+ print(" Added an entry to ipv4_host: {} --> set_nexthop({})".
+ format(ipv4_dst, nexthop_id))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+ pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, ingress_port, pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the packet to be forwarded to port {}"
+ .format(egress_port))
+ verify_packet(self, pkt, egress_port)
+ print(" Packet received of port {}".format(egress_port))
+
+
+class HostDrop(BaseProgramTest):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in nexthop: nexthop_id --> drop()
+ #
+ key_list = [
+ self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+ ]
+
+ data_list = [
+ self.nexthop.make_data([], "Ingress.drop")
+ ]
+
+ self.nexthop.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to nexthop: {} --> drop()".
+ format(nexthop_id))
+
+ #
+ # Program an entry in ipv4_host: ipv4_dst --> set_nexthop(nexthop_id)
+ #
+ key_list = [
+ self.ipv4_host.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr', ipv4_dst)])
+ ]
+
+ data_list = [
+ self.ipv4_host.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+ ]
+
+ self.ipv4_host.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to ipv4_host: {} --> drop()".format(
+ ipv4_dst))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+ pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, ingress_port, pkt)
+ print(" Expecting No packets anywhere")
+
+ #
+ # Wait to make sure no packet egresses anywhere. self.swports is the
+ # list of all ports the test is using. It is set up in the setUp()
+ # method of the parent class
+ #
+ verify_no_packet_any(self, pkt, self.swports)
+ print(" No packets received")
+
+class HostL3Switch(BaseProgramTest):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ new_mac_da = test_param_get("new_mac_da", "00:12:34:56:78:9A")
+ new_mac_sa = test_param_get("new_mac_sa", "00:00:AA:BB:CC:DD")
+ egress_port = test_param_get("egress_port", 4)
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in nexthop:
+ # nexthop_id --> l3_switch(egress_port. new_mac_da, new_mac_da)
+ #
+ key = self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+
+ data = self.nexthop.make_data([
+ gc.DataTuple('port', egress_port),
+ gc.DataTuple('new_mac_da', new_mac_da),
+ gc.DataTuple('new_mac_sa', new_mac_sa)],
+ "Ingress.l3_switch")
+
+ self.nexthop.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to nexthop: {} --> l3_switch({}, {}, {})".
+ format(nexthop_id, egress_port, new_mac_da, new_mac_sa))
+
+ #
+ # Program an entry in IPv4: ipv4_dst --> set_nexthop(nexthop_id)
+ #
+ key = self.ipv4_host.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr', ipv4_dst)])
+
+ data = self.ipv4_host.make_data([
+ gc.DataTuple('id', nexthop_id)],
+ "Ingress.set_nexthop")
+
+ self.ipv4_host.entry_add(self.dev_tgt, [key], [data]);
+ print(" Added an entry to ipv4_host: {} --> set_nexthop({})".
+ format(ipv4_dst, nexthop_id))
+
+ #
+ # Prepare the test packet and the expected packet
+ send_pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+
+ exp_pkt = copy.deepcopy(send_pkt)
+ exp_pkt[Ether].dst = new_mac_da
+ exp_pkt[Ether].src = new_mac_sa
+ exp_pkt[IP].ttl -= 1
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+
+ send_packet(self, ingress_port, send_pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the modified packet to be forwarded to port {}"
+ .format(egress_port))
+
+ verify_packet(self, exp_pkt, egress_port)
+ print(" Modified Packet received of port {}"
+ .format(egress_port))
+
+class LpmSend(BaseProgramTest):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ lpm_addr = test_param_get("lpm_addr", "192.168.1.0/24")
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ egress_port = test_param_get("egress_port", 4)
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ (lpm_ipv4, lpm_p_len) = lpm_addr.split("/")
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in nexthop: nexthop_id --> send(egress_port)
+ #
+ key_list = [
+ self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+ ]
+
+ data_list = [
+ self.nexthop.make_data([
+ gc.DataTuple('port', egress_port)], "Ingress.send")
+ ]
+
+ self.nexthop.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to nexthop: {} --> send({})".format(
+ nexthop_id, egress_port))
+
+ #
+ # Program an entry in ipv4_lpm:
+ # lpm_addr/prefix --> set_nexthop(nexthop_id)
+ # Note the extra named argument (prefix_len) to gc.KeyTuple().
+ #
+ key_list = [
+ self.ipv4_lpm.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr',
+ value=lpm_ipv4, prefix_len=int(lpm_p_len))])
+ ]
+
+ data_list = [
+ self.ipv4_lpm.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+ ]
+
+ self.ipv4_lpm.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to ipv4_lpm: {}/{} --> set_nexthop({})".format(
+ lpm_ipv4, lpm_p_len, nexthop_id))
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}".
+ format(ipv4_dst, ingress_port))
+ pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, ingress_port, pkt)
+
+ #
+ # Wait for the egress packet and verify it. Since we do not expect
+ # any modifications, we use the same pkt.
+ #
+ print(" Expecting the packet to be forwarded to port {}".
+ format(egress_port))
+
+ verify_packet(self, pkt, egress_port)
+ print(" Packet received on port {}".format(egress_port))
+
+class LpmDrop(BaseProgramTest):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ lpm_addr = test_param_get("lpm_addr", "192.168.1.0/24")
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ (lpm_ipv4, lpm_p_len) = lpm_addr.split("/")
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in nexthop: nexthop_id --> drop()
+ #
+ key_list = [
+ self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+ ]
+
+ data_list = [
+ self.nexthop.make_data([], "Ingress.drop")
+ ]
+
+ self.nexthop.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to nexthop: {} --> drop()".
+ format(nexthop_id))
+
+ #
+ # Program an entry in ipv4_lpm:
+ # lpm_addr/prefix --> set_nexthop(nexthop_id)
+ # Note the extra named argument (prefix_len) to gc.KeyTuple().
+ #
+ key_list = [
+ self.ipv4_lpm.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr',
+ value=lpm_ipv4, prefix_len=int(lpm_p_len))])
+ ]
+
+ data_list = [
+ self.ipv4_lpm.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+ ]
+
+ self.ipv4_lpm.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to ipv4_lpm: {}/{} --> set_nexthop({})".format(
+ lpm_ipv4, lpm_p_len, nexthop_id))
+
+ #
+ # Send the Test Packet
+ #
+ print(" Sending packet with IPv4 DST ADDR{} into port {}".
+ format(ipv4_dst, ingress_port))
+
+ pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ send_packet(self, ingress_port, pkt)
+
+ print(" Expecting No packets anywhere")
+ verify_no_packet_any(self, pkt, self.swports)
+ print(" No packets received")
+
+class LpmL3Switch(BaseProgramTest):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ lpm_addr = test_param_get("lpm_addr", "192.168.1.0/24")
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ new_mac_da = test_param_get("new_mac_da", "00:12:34:56:78:9A")
+ new_mac_sa = test_param_get("new_mac_sa", "00:00:AA:BB:CC:DD")
+ egress_port = test_param_get("egress_port", 4)
+ nexthop_id = test_param_get("nexthop_id", 100)
+
+ (lpm_ipv4, lpm_p_len) = lpm_addr.split("/")
+
+ print("\n")
+ print("Test Run")
+ print("========")
+
+ #
+ # Program an entry in nexthop:
+ # nexthop_id --> l3_switch(egress_port. new_mac_da, new_mac_da)
+ #
+ key_list = [
+ self.nexthop.make_key([
+ gc.KeyTuple('nexthop_id', nexthop_id)])
+ ]
+
+ data_list = [
+ self.nexthop.make_data([gc.DataTuple('port', egress_port),
+ gc.DataTuple('new_mac_da', new_mac_da),
+ gc.DataTuple('new_mac_sa', new_mac_sa)],
+ "Ingress.l3_switch")
+ ]
+
+ self.nexthop.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to nexthop: {} --> send({})".
+ format(nexthop_id, egress_port))
+
+ #
+ # Program an entry in ipv4_lpm:
+ # lpm_addr/prefix --> set_nexthop(nexthop_id)
+ # Note the extra named argument (prefix_len) to gc.KeyTuple().
+ #
+ key_list = [
+ self.ipv4_lpm.make_key([
+ gc.KeyTuple('hdr.ipv4.dst_addr',
+ value=lpm_ipv4, prefix_len=int(lpm_p_len))])
+ ]
+
+ data_list = [
+ self.ipv4_lpm.make_data([
+ gc.DataTuple('id', nexthop_id)], "Ingress.set_nexthop")
+ ]
+
+ self.ipv4_lpm.entry_add(self.dev_tgt, key_list, data_list);
+ print(" Added an entry to ipv4_lpm: {}/{} --> set_nexthop({})".format(
+ lpm_ipv4, lpm_p_len, nexthop_id))
+ #
+ # Prepare the test packet and the expected packet
+ #
+ send_pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+
+ exp_pkt = copy.deepcopy(send_pkt)
+ exp_pkt[Ether].dst = new_mac_da
+ exp_pkt[Ether].src = new_mac_sa
+ exp_pkt[IP].ttl -= 1
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}".
+ format(ipv4_dst, ingress_port))
+
+ send_packet(self, ingress_port, send_pkt)
+
+ #
+ # Wait for the egress packet and verify it
+ #
+ print(" Expecting the modified packet to be forwarded to port {}".
+ format(egress_port))
+ verify_packet(self, exp_pkt, egress_port)
+ print(" Modified Packet received of port {}".format(egress_port))
+
+########################################################################
+######## Running Multiple Tests with the same setup ###############
+########################################################################
+
+# This new Base Class extends the setup method of Simple L3 by adding the
+# desired network setup
+class TestGroup1(BaseProgramTest):
+
+ #
+ # This is a simple function that takes a list of entries and programs
+ # them in a specified table
+ #
+ # Each entry is a tuple, consisting of 3 elements:
+ # key -- a list of tuples for each element of the key
+ # action_name -- the action to use. Must use full name of the action
+ # data -- a list (may be empty) of the tuples for each action
+ # parameter
+ #
+ def programTable(self, table, entries, target=None):
+ if target is None:
+ target = self.dev_tgt
+
+ key_list=[]
+ data_list=[]
+ for k, a, d in entries:
+ key_list.append(table.make_key([gc.KeyTuple(*f) for f in k]))
+ data_list.append(table.make_data([gc.DataTuple(*p) for p in d], a))
+ table.entry_add(target, key_list, data_list)
+
+ def setUp(self):
+ BaseProgramTest.setUp(self)
+
+ print("\n")
+ print("Table Setup")
+ print("===========")
+
+ # Nexthop programming
+ print(" nexthop")
+ self.programTable(self.nexthop, [
+ ([("nexthop_id", 0)], "Ingress.send", [("port", 64)]),
+ ([("nexthop_id", 1)], "Ingress.drop", []),
+ ([("nexthop_id", 101)], "Ingress.l3_switch", [
+ ("port", 1),
+ ("new_mac_da", "00:00:01:00:00:01"),
+ ("new_mac_sa", "00:00:FF:00:00:FE")]),
+ ([("nexthop_id", 102)], "Ingress.l3_switch", [
+ ("port", 2),
+ ("new_mac_da", "00:00:02:00:00:01"),
+ ("new_mac_sa", "00:00:FF:00:00:FE")]),
+ ([("nexthop_id", 103)], "Ingress.l3_switch", [
+ ("port", 4),
+ ("new_mac_da", "FF:FF:FF:FF:FF:FF"),
+ ("new_mac_sa", "00:12:34:56:78:9A")])
+ ])
+
+ # ipv4_host programming
+ print(" ipv4_host")
+ self.programTable(self.ipv4_host, [
+ ([("hdr.ipv4.dst_addr", "192.168.1.1")],
+ "Ingress.set_nexthop", [("id", 101)]),
+ ([("hdr.ipv4.dst_addr", "192.168.1.2")],
+ "Ingress.set_nexthop", [("id", 102)]),
+ ([("hdr.ipv4.dst_addr", "192.168.1.3")],
+ "Ingress.set_nexthop", [("id", 1)]),
+ ([("hdr.ipv4.dst_addr", "192.168.1.254")],
+ "Ingress.set_nexthop", [("id", 0)]),
+ ])
+
+ # ipv4_lpm programming
+ print(" ipv4_lpm")
+ self.programTable(self.ipv4_lpm, [
+ ([("hdr.ipv4.dst_addr", "192.168.1.0", None, 24)],
+ "Ingress.set_nexthop", [("id", 0)]),
+ ([("hdr.ipv4.dst_addr", "192.168.3.0", None, 24)],
+ "Ingress.set_nexthop", [("id", 101)]),
+ ([("hdr.ipv4.dst_addr", "192.168.5.0", None, 24)],
+ "Ingress.set_nexthop", [("id", 101)]),
+ ([("hdr.ipv4.dst_addr", "192.168.7.0", None, 24)],
+ "Ingress.set_nexthop", [("id", 101)]),
+ ([("hdr.ipv4.dst_addr", "192.168.0.0", None, 16)],
+ "Ingress.set_nexthop", [("id", 1)]),
+ ([("hdr.ipv4.dst_addr", "0.0.0.0", None, 0)],
+ "Ingress.set_nexthop", [("id", 0)]),
+ ])
+
+#
+# The following are multiple tests that all use the same setup
+#
+# There are a lot of tests that can be run on this topology. Feel free to
+# add more
+#
+
+class BadTTL(TestGroup1):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ ttl = test_param_get("ttl", 1)
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+ pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=ttl,
+ ip_ihl=5)
+ send_packet(self, ingress_port, pkt)
+ print(" Expecting No packets anywhere")
+
+ #
+ # Wait to make sure no packet egresses anywhere. self.swports is the
+ # list of all ports the test is using. It is set up in the setUp()
+ # method of the parent class
+ #
+ verify_no_packet_any(self, pkt, self.swports)
+ print(" No packets received")
+
+class BadChecksum(TestGroup1):
+ def runTest(self):
+ ingress_port = test_param_get("ingress_port", 0)
+ ipv4_dst = test_param_get("ipv4_dst", "192.168.1.1")
+ chksum = test_param_get("chksum", 123)
+
+ #
+ # Send a test packet
+ #
+ print(" Sending packet with IPv4 DST ADDR={} into port {}"
+ .format(ipv4_dst, ingress_port))
+ pkt = simple_tcp_packet(eth_dst="00:98:76:54:32:10",
+ eth_src='00:55:55:55:55:55',
+ ip_dst=ipv4_dst,
+ ip_id=101,
+ ip_ttl=64,
+ ip_ihl=5)
+ # Corrupt checksum
+ pkt[IP].chksum = chksum
+
+ send_packet(self, ingress_port, pkt)
+ print(" Expecting No packets anywhere")
+
+ #
+ # Wait to make sure no packet egresses anywhere. self.swports is the
+ # list of all ports the test is using. It is set up in the setUp()
+ # method of the parent class
+ #
+ verify_no_packet_any(self, pkt, self.swports)
+ print(" No packets received")