diff --git a/dash-pipeline/Makefile b/dash-pipeline/Makefile index 82abcba44..5d15844cf 100644 --- a/dash-pipeline/Makefile +++ b/dash-pipeline/Makefile @@ -11,7 +11,7 @@ DOCKER_RUN := docker run \ --network=host \ --rm -bmv2/dash_pipeline.bmv2/dash_pipeline.json: +bmv2/dash_pipeline.bmv2/dash_pipeline.json: bmv2/*.p4 $(DOCKER_RUN) bmv2-$(USER) p4c \ -b \ bmv2 \ diff --git a/dash-pipeline/bmv2/dash_acl.p4 b/dash-pipeline/bmv2/dash_acl.p4 index 963957516..0b68e9724 100644 --- a/dash-pipeline/bmv2/dash_acl.p4 +++ b/dash-pipeline/bmv2/dash_acl.p4 @@ -28,7 +28,7 @@ match_kind { @name(str(table_name##:dash_acl|dash_acl)) \ table table_name { \ key = { \ - meta.eni_id : exact @name("meta.eni_id:eni_id"); \ + meta. ## table_name ##_acl_group_id : exact @name("meta.acl_group_id:acl_group_id"); \ hdr.ipv4.dst_addr : LIST_MATCH @name("hdr.ipv4.dst_addr:dip"); \ hdr.ipv4.src_addr : LIST_MATCH @name("hdr.ipv4.src_addr:sip"); \ hdr.ipv4.protocol : LIST_MATCH @name("hdr.ipv4.src_addr:protocol"); \ @@ -51,7 +51,7 @@ match_kind { deny: {return;} \ } -/* +/* * This control results in a new set of tables every time * it is applied, i. e. inbound ACL tables are different * from outbound, and API will be generated for each of them diff --git a/dash-pipeline/bmv2/dash_inbound.p4 b/dash-pipeline/bmv2/dash_inbound.p4 deleted file mode 100644 index becc3148b..000000000 --- a/dash-pipeline/bmv2/dash_inbound.p4 +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _SIRIUS_INBOUND_P4_ -#define _SIRIUS_INBOUND_P4_ - -#include "dash_headers.p4" -#include "dash_service_tunnel.p4" -#include "dash_vxlan.p4" -#include "dash_acl.p4" -#include "dash_conntrack.p4" - -control inbound(inout headers_t hdr, - inout metadata_t meta, - inout standard_metadata_t standard_metadata) -{ - action set_vm_attributes(EthernetAddress underlay_dmac, - IPv4Address underlay_dip, - bit<24> vni) { - meta.encap_data.underlay_dmac = underlay_dmac; - meta.encap_data.underlay_dip = underlay_dip; - meta.encap_data.vni = vni; - } - - action set_vm_id(bit<16> inbound_vm_id) { - meta.inbound_vm_id = inbound_vm_id; - } - - @name("eni_to_vm|dash_vnet") - table eni_to_vm { - key = { - meta.eni_id: exact @name("meta.eni_id:eni_id"); - } - - actions = { - set_vm_id; - } - } - - @name("vm|dash_vnet") - table vm { - key = { - meta.inbound_vm_id: exact @name("meta.inbound_vm_id:inbound_vm_id"); - } - - actions = { - set_vm_attributes; - } - } - - apply { - eni_to_vm.apply(); - - vm.apply(); - - /* Check if PA is valid */ - -#ifdef STATEFUL_P4 - ConntrackIn.apply(0); -#endif /* STATEFUL_P4 */ -#ifdef PNA_CONNTRACK - ConntrackIn.apply(hdr, meta); -#endif // PNA_CONNTRACK - - /* ACL */ - if (!meta.conntrack_data.allow_in) { - acl.apply(hdr, meta, standard_metadata); - } - -#ifdef STATEFUL_P4 - ConntrackOut.apply(1); -#endif /* STATEFUL_P4 */ -#ifdef PNA_CONNTRACK - ConntrackOut.apply(hdr, meta); -#endif //PNA_CONNTRACK - - vxlan_encap(hdr, - meta.encap_data.underlay_dmac, - meta.encap_data.underlay_smac, - meta.encap_data.underlay_dip, - meta.encap_data.underlay_sip, - hdr.ethernet.dst_addr, - meta.encap_data.vni); - } -} - -#endif /* _SIRIUS_INBOUND_P4_ */ diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index e7dc169a2..ccf9fea5a 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -38,10 +38,18 @@ struct metadata_t { EthernetAddress eni_addr; bit<16> eni_id; eni_data_t eni_data; - bit<16> inbound_vm_id; + bit<16> stage1_acl_group_id; + bit<16> stage2_acl_group_id; + bit<16> stage3_acl_group_id; + bit<16> acl_group_id; + bit<16> route_table_id; + bit<16> tunnel_id; + bit<16> vnet; + bit<24> lookup_vni; bit<8> appliance_id; bit<1> is_dst_ip_v6; IPv4ORv6Address dst_ip_addr; + IPv4Address pa_src; conntrack_data_t conntrack_data; } diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index 2d14afe46..5dcdd64fb 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -2,28 +2,11 @@ #define _SIRIUS_OUTBOUND_P4_ #include "dash_headers.p4" -#include "dash_acl.p4" -#include "dash_conntrack.p4" control outbound(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t standard_metadata) { - action set_vni(bit<24> vni) { - meta.encap_data.vni = vni; - } - - @name("eni_to_vni|dash_vnet") - table eni_to_vni { - key = { - meta.eni_id : exact @name("meta.eni_id:eni_id"); - } - - actions = { - set_vni; - } - } - action route_vnet(bit<24> dest_vnet_vni) { meta.encap_data.dest_vnet_vni = dest_vnet_vni; } @@ -33,7 +16,7 @@ control outbound(inout headers_t hdr, @name("routing|dash_vnet") table routing { key = { - meta.eni_id : exact @name("meta.eni_id:eni_id"); + meta.route_table_id : exact @name("meta.route_table_id:route_table_id"); meta.is_dst_ip_v6 : exact @name("meta.is_dst_ip_v6:v4_or_v6"); meta.dst_ip_addr : lpm @name("meta.dst_ip_addr:destination"); } @@ -45,7 +28,7 @@ control outbound(inout headers_t hdr, counters = routing_counter; } - action set_tunnel_mapping(IPv4Address underlay_dip, + action set_tunnel_mapping(bit<16> tunnel_id, EthernetAddress overlay_dmac, bit<1> use_dst_vni) { /* @@ -56,7 +39,7 @@ control outbound(inout headers_t hdr, */ meta.encap_data.vni = meta.encap_data.vni * (bit<24>)(~use_dst_vni) + meta.encap_data.dest_vnet_vni * (bit<24>)use_dst_vni; meta.encap_data.overlay_dmac = overlay_dmac; - meta.encap_data.underlay_dip = underlay_dip; + meta.tunnel_id = tunnel_id; } direct_counter(CounterType.packets_and_bytes) ca_to_pa_counter; @@ -78,40 +61,9 @@ control outbound(inout headers_t hdr, } apply { - eni_to_vni.apply(); - -#ifdef STATEFUL_P4 - ConntrackOut.apply(0); -#endif /* STATEFUL_P4 */ - -#ifdef PNA_CONNTRACK - ConntrackOut.apply(hdr, meta); -#endif // PNA_CONNTRACK - - /* ACL */ - if (!meta.conntrack_data.allow_out) { - acl.apply(hdr, meta, standard_metadata); - } - -#ifdef STATEFUL_P4 - ConntrackIn.apply(1); -#endif /* STATEFUL_P4 */ - -#ifdef PNA_CONNTRACK - ConntrackIn.apply(hdr, meta); -#endif // PNA_CONNTRACK - switch (routing.apply().action_run) { route_vnet: { ca_to_pa.apply(); - - vxlan_encap(hdr, - meta.encap_data.underlay_dmac, - meta.encap_data.underlay_smac, - meta.encap_data.underlay_dip, - meta.encap_data.underlay_sip, - meta.encap_data.overlay_dmac, - meta.encap_data.vni); } } } diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index dc201d9e4..70de11db8 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -5,11 +5,11 @@ #include "dash_parser.p4" #include "dash_vxlan.p4" #include "dash_outbound.p4" -#include "dash_inbound.p4" #include "dash_conntrack.p4" +#include "dash_acl.p4" control dash_verify_checksum(inout headers_t hdr, - inout metadata_t meta) + inout metadata_t meta) { apply { } } @@ -86,17 +86,42 @@ control dash_ingress(inout headers_t hdr, action set_eni_attrs(bit<32> cps, bit<32> pps, bit<32> flows, - bit<1> admin_state) { - meta.eni_data.cps = cps; - meta.eni_data.pps = pps; - meta.eni_data.flows = flows; + bit<1> admin_state, + bit<16> eni_id, + bit<24> vni, + bit<16> stage1_outbound_acl_group_id, + bit<16> stage1_inbound_acl_group_id, + bit<16> stage2_outbound_acl_group_id, + bit<16> stage2_inbound_acl_group_id, + bit<16> stage3_outbound_acl_group_id, + bit<16> stage3_inbound_acl_group_id, + bit<16> route_table_id, + bit<16> vnet_id, + bit<16> tunnel_id) { + meta.eni_data.cps = cps; + meta.eni_data.pps = pps; + meta.eni_data.flows = flows; meta.eni_data.admin_state = admin_state; + meta.eni_id = eni_id; + meta.encap_data.vni = vni; + if (meta.direction == direction_t.OUTBOUND) { + meta.stage1_acl_group_id = stage1_outbound_acl_group_id; + meta.stage2_acl_group_id = stage2_outbound_acl_group_id; + meta.stage3_acl_group_id = stage3_outbound_acl_group_id; + } else { + meta.stage1_acl_group_id = stage1_inbound_acl_group_id; + meta.stage2_acl_group_id = stage2_inbound_acl_group_id; + meta.stage3_acl_group_id = stage3_inbound_acl_group_id; + } + meta.route_table_id = route_table_id; + meta.vnet = vnet_id; + meta.tunnel_id = tunnel_id; } @name("eni|dash") table eni { key = { - meta.eni_id : exact @name("meta.eni_id:eni_id"); + meta.eni_addr : exact @name("meta.eni_addr:address"); } actions = { @@ -118,18 +143,16 @@ control dash_ingress(inout headers_t hdr, counters = eni_counter; } - action permit() { - meta.dropped = false; - } + action permit() {} - action vxlan_decap_pa_validate() {} + action pa_validate() {} @name("pa_validation|dash_vnet") table pa_validation { key = { meta.eni_id: exact @name("meta.eni_id:eni_id"); - hdr.ipv4.src_addr : exact @name("hdr.ipv4.src_addr:sip"); - hdr.vxlan.vni : exact @name("hdr.vxlan.vni:VNI"); + meta.pa_src : exact @name("meta.pa_src:sip"); + meta.lookup_vni : exact @name("meta.lookup_vni:VNI"); } actions = { @@ -140,35 +163,20 @@ control dash_ingress(inout headers_t hdr, const default_action = deny; } - @name("inbound_routing|dash_vnet") - table inbound_routing { + @name("vnet|dash_vnet") + table vnet { key = { - hdr.vxlan.vni : exact @name("hdr.vxlan.vni:VNI"); + meta.lookup_vni : exact @name("meta.lookup_vni:vni"); } actions = { - vxlan_decap(hdr); - vxlan_decap_pa_validate; + permit; + pa_validate; @defaultonly deny; } const default_action = deny; } - action set_eni(bit<16> eni_id) { - meta.eni_id = eni_id; - } - - @name("eni_ether_address_map|dash") - table eni_ether_address_map { - key = { - meta.eni_addr : exact @name("meta.eni_addr:address"); - } - - actions = { - set_eni; - } - } - apply { vip.apply(); if (meta.dropped) { @@ -181,17 +189,11 @@ control dash_ingress(inout headers_t hdr, appliance.apply(); /* Outer header processing */ + meta.lookup_vni = hdr.vxlan.vni; + meta.pa_src = hdr.ipv4.src_addr; + vxlan_decap(hdr); - if (meta.direction == direction_t.OUTBOUND) { - vxlan_decap(hdr); - } else if (meta.direction == direction_t.INBOUND) { - switch (inbound_routing.apply().action_run) { - vxlan_decap_pa_validate: { - pa_validation.apply(); - vxlan_decap(hdr); - } - } - } + /* At this point the processing is done on customer headers */ meta.dst_ip_addr = 0; meta.is_dst_ip_v6 = 0; @@ -202,13 +204,10 @@ control dash_ingress(inout headers_t hdr, meta.dst_ip_addr = (bit<128>)hdr.ipv4.dst_addr; } - /* At this point the processing is done on customer headers */ - /* Put VM's MAC in the direction agnostic metadata field */ meta.eni_addr = meta.direction == direction_t.OUTBOUND ? hdr.ethernet.src_addr : hdr.ethernet.dst_addr; - eni_ether_address_map.apply(); eni.apply(); if (meta.eni_data.admin_state == 0) { deny(); @@ -216,15 +215,68 @@ control dash_ingress(inout headers_t hdr, } if (meta.direction == direction_t.OUTBOUND) { - outbound.apply(hdr, meta, standard_metadata); + meta.lookup_vni = meta.encap_data.vni; + } + switch (vnet.apply().action_run) { + pa_validate: { + pa_validation.apply(); + } + } + + if (meta.direction == direction_t.OUTBOUND) { +#ifdef STATEFUL_P4 + ConntrackOut.apply(0); +#endif /* STATEFUL_P4 */ + +#ifdef PNA_CONNTRACK + ConntrackOut.apply(hdr, meta); +#endif // PNA_CONNTRACK + } else { +#ifdef STATEFUL_P4 + ConntrackIn.apply(0); +#endif /* STATEFUL_P4 */ +#ifdef PNA_CONNTRACK + ConntrackIn.apply(hdr, meta); +#endif // PNA_CONNTRACK + } + + /* ACL */ + if (!meta.conntrack_data.allow_out) { + acl.apply(hdr, meta, standard_metadata); + } + + if (meta.direction == direction_t.OUTBOUND) { +#ifdef STATEFUL_P4 + ConntrackIn.apply(1); +#endif /* STATEFUL_P4 */ + +#ifdef PNA_CONNTRACK + ConntrackIn.apply(hdr, meta); +#endif // PNA_CONNTRACK } else if (meta.direction == direction_t.INBOUND) { - inbound.apply(hdr, meta, standard_metadata); +#ifdef STATEFUL_P4 + ConntrackOut.apply(1); +#endif /* STATEFUL_P4 */ +#ifdef PNA_CONNTRACK + ConntrackOut.apply(hdr, meta); +#endif //PNA_CONNTRACK + + } + + if (meta.direction == direction_t.OUTBOUND) { + outbound.apply(hdr, meta, standard_metadata); + } else { + meta.encap_data.overlay_dmac = hdr.ethernet.dst_addr; } eni_meter.apply(); /* Send packet to port 1 by default if we reached the end of pipeline */ - standard_metadata.egress_spec = 1; + if (meta.dropped) { + drop_action(); + } else { + standard_metadata.egress_spec = 1; + } } } @@ -232,7 +284,36 @@ control dash_egress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t standard_metadata) { - apply { } + action set_tunnel_attributes(EthernetAddress underlay_dmac, + IPv4Address underlay_dip, + bit<24> vni) { + meta.encap_data.underlay_dmac = underlay_dmac; + meta.encap_data.underlay_dip = underlay_dip; + meta.encap_data.vni = vni; + } + + @name("dash_tunnel|dash_vnet") + table tunnel { + key = { + meta.tunnel_id: exact @name("meta.tunnel_id:tunnel_id"); + } + + actions = { + set_tunnel_attributes; + } + } + + apply { + tunnel.apply(); + + vxlan_encap(hdr, + meta.encap_data.underlay_dmac, + meta.encap_data.underlay_smac, + meta.encap_data.underlay_dip, + meta.encap_data.underlay_sip, + meta.encap_data.overlay_dmac, + meta.encap_data.vni); + } } V1Switch(dash_parser(), diff --git a/dash-pipeline/tests/vnet_out/vnet_out.cpp b/dash-pipeline/tests/vnet_out/vnet_out.cpp index 9f80ec668..669eb854e 100644 --- a/dash-pipeline/tests/vnet_out/vnet_out.cpp +++ b/dash-pipeline/tests/vnet_out/vnet_out.cpp @@ -10,13 +10,8 @@ extern sai_status_t sai_create_direction_lookup_entry( _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); -extern sai_status_t sai_create_eni_ether_address_map_entry( - _In_ const sai_eni_ether_address_map_entry_t *outbound_eni_lookup_from_vm_entry, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list); - -extern sai_status_t sai_create_outbound_eni_to_vni_entry( - _In_ const sai_outbound_eni_to_vni_entry_t *outbound_eni_to_vni_entry, +extern sai_status_t sai_create_eni_entry( + _In_ const sai_eni_entry_t *eni_entry, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); @@ -35,7 +30,7 @@ int main(int argc, char **argv) attr.id = SAI_DIRECTION_LOOKUP_ENTRY_ATTR_ACTION; attr.value.u32 = SAI_DIRECTION_LOOKUP_ENTRY_ACTION_SET_OUTBOUND_DIRECTION; attrs.push_back(attr); - + /* sai_status_t status = sai_dash_api_impl.create_direction_lookup_entry(&dle, attrs.size(), attrs.data()); */ sai_status_t status = sai_create_direction_lookup_entry(&dle, attrs.size(), attrs.data()); if (status != SAI_STATUS_SUCCESS) @@ -46,7 +41,7 @@ int main(int argc, char **argv) attrs.clear(); - sai_eni_ether_address_map_entry_t eam; + sai_eni_entry_t eam; eam.switch_id = switch_id; eam.address[0] = 0xaa; eam.address[1] = 0xcc; @@ -55,38 +50,75 @@ int main(int argc, char **argv) eam.address[4] = 0xcc; eam.address[5] = 0xcc; - attr.id = SAI_ENI_ETHER_ADDRESS_MAP_ENTRY_ATTR_ENI_ID; + attr.id = SAI_ENI_ENTRY_ATTR_ENI_ID; attr.value.u16 = 7; attrs.push_back(attr); - status = sai_create_eni_ether_address_map_entry(&eam, attrs.size(), attrs.data()); - if (status != SAI_STATUS_SUCCESS) - { - std::cout << "Failed to create ENI Lookup From VM" << std::endl; - return 1; - } + attr.id = SAI_ENI_ENTRY_ATTR_VNI; + attr.value.u16 = 9; + attrs.push_back(attr); - attrs.clear(); + attr.id = SAI_ENI_ENTRY_ATTR_TUNNEL_ID; + attr.value.u16 = 2; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_ROUTE_TABLE_ID; + attr.value.u16 = 2; + attrs.push_back(attr); - sai_outbound_eni_to_vni_entry_t e2v = {}; - e2v.switch_id = switch_id; - e2v.eni_id = 7; + attr.id = SAI_ENI_ENTRY_ATTR_STAGE1_OUTBOUND_ACL_GROUP_ID, + attr.value.u16 = 2; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_STAGE1_INBOUND_ACL_GROUP_ID, + attr.value.u16 = 2; + attrs.push_back(attr); - attr.id = SAI_OUTBOUND_ENI_TO_VNI_ENTRY_ATTR_VNI; - attr.value.u32 = 9; + attr.id = SAI_ENI_ENTRY_ATTR_STAGE2_OUTBOUND_ACL_GROUP_ID, + attr.value.u16 = 2; attrs.push_back(attr); - /* status = sai_dash_api_impl.create_outbound_eni_to_vni_entry(&e2v, attrs.size(), attrs.data()); */ - status = sai_create_outbound_eni_to_vni_entry(&e2v, attrs.size(), attrs.data()); + attr.id = SAI_ENI_ENTRY_ATTR_STAGE2_INBOUND_ACL_GROUP_ID, + attr.value.u16 = 2; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_STAGE3_OUTBOUND_ACL_GROUP_ID, + attr.value.u16 = 2; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_STAGE3_INBOUND_ACL_GROUP_ID, + attr.value.u16 = 2; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_CPS, + attr.value.u16 = 1000; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_PPS, + attr.value.u16 = 10000; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_FLOWS, + attr.value.u16 = 100; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_VNET_ID, + attr.value.u16 = 2; + attrs.push_back(attr); + + attr.id = SAI_ENI_ENTRY_ATTR_ADMIN_STATE, + attr.value.booldata = true; + attrs.push_back(attr); + + status = sai_create_eni_entry(&eam, attrs.size(), attrs.data()); if (status != SAI_STATUS_SUCCESS) { - std::cout << "Failed to create ENI To VNI" << std::endl; + std::cout << "Failed to create ENI entry" << std::endl; return 1; } attrs.clear(); - std::cout << "Done." << std::endl; return 0;