diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 34502d232..9238914e2 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -14,6 +14,7 @@ TABLES_TAG = 'tables' BITWIDTH_TAG = 'bitwidth' ACTIONS_TAG = 'actions' +ACTION_PARAMS_TAG = 'actionParams' PREAMBLE_TAG = 'preamble' OTHER_MATCH_TYPE_TAG = 'otherMatchType' MATCH_TYPE_TAG = 'matchType' @@ -22,6 +23,7 @@ MATCH_FIELDS_TAG = 'matchFields' NOACTION = 'NoAction' STAGES_TAG = 'stages' +PARAM_ACTIONS = 'paramActions' def get_sai_key_type(key_size, key_header, key_field): if key_size == 1: @@ -97,7 +99,7 @@ def get_sai_key_data(key): sai_key_data['sai_key_name'] = sai_key_name key_size = key[BITWIDTH_TAG] - + if OTHER_MATCH_TYPE_TAG in key: sai_key_data['match_type'] = key[OTHER_MATCH_TYPE_TAG].lower() elif MATCH_TYPE_TAG in key: @@ -145,6 +147,21 @@ def table_with_counters(program, table_id): return 'true' return 'false' +def fill_action_params(table_params, param_names, action): + for param in action[PARAMS_TAG]: + # skip v4/v6 selector + if 'v4_or_v6' in param[NAME_TAG]: + continue + if param[NAME_TAG] not in param_names: + param_names.append(param[NAME_TAG]) + param[PARAM_ACTIONS] = [action[NAME_TAG]] + table_params.append(param) + else: + # ensure that same param passed to multiple actions of the + # same P4 table does not generate more than 1 SAI attribute + for tbl_param in table_params: + if tbl_param[NAME_TAG] == param[NAME_TAG]: + tbl_param[PARAM_ACTIONS].append(action[NAME_TAG]) def generate_sai_apis(program, ignore_tables): sai_apis = [] @@ -155,6 +172,7 @@ def generate_sai_apis(program, ignore_tables): sai_table_data['keys'] = [] sai_table_data[ACTIONS_TAG] = [] sai_table_data[STAGES_TAG] = [] + sai_table_data[ACTION_PARAMS_TAG] = [] table_control, table_name = table[PREAMBLE_TAG][NAME_TAG].split('.', 1) if table_name in ignore_tables: @@ -189,9 +207,11 @@ def generate_sai_apis(program, ignore_tables): continue sai_table_data['keys'].append(get_sai_key_data(key)) + param_names = [] for action in table[ACTION_REFS_TAG]: action_id = action["id"] if all_actions[action_id][NAME_TAG] != NOACTION: + fill_action_params(sai_table_data[ACTION_PARAMS_TAG], param_names, all_actions[action_id]) sai_table_data[ACTIONS_TAG].append(all_actions[action_id]) if len(sai_table_data['keys']) == 1 and sai_table_data['keys'][0]['sai_key_name'].endswith(table_name.split('.')[-1] + '_id'): diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 98ca79195..dc236165a 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -103,8 +103,7 @@ sai_status_t sai_create_{{ table.name }}( for (uint32_t i = 0; i < attr_count; i++) { switch(attr_list[i].id) { - {% for action in table.actions %} - {% for param in action.params %} + {% for param in table.actionParams %} case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: { auto param = action->add_params(); param->set_param_id({{param.id}}); @@ -113,7 +112,6 @@ sai_status_t sai_create_{{ table.name }}( break; } {% endfor %} - {% endfor %} } } @@ -222,8 +220,7 @@ sai_status_t sai_create_{{ table.name }}( for (uint32_t i = 0; i < attr_count; i++) { switch(attr_list[i].id) { - {% for action in table.actions %} - {% for param in action.params %} + {% for param in table.actionParams %} case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: { auto param = action->add_params(); param->set_param_id({{param.id}}); @@ -232,7 +229,6 @@ sai_status_t sai_create_{{ table.name }}( break; } {% endfor %} - {% endfor %} } } diff --git a/dash-pipeline/SAI/templates/saiapi.h.j2 b/dash-pipeline/SAI/templates/saiapi.h.j2 index 56adc34d2..4f9e3898e 100644 --- a/dash-pipeline/SAI/templates/saiapi.h.j2 +++ b/dash-pipeline/SAI/templates/saiapi.h.j2 @@ -151,19 +151,15 @@ typedef enum _sai_{{ table.name }}_attr_t {% endfor %} {% endif %} -{% for action in table.actions %} -{% for param in action.params %} +{% for param in table.actionParams %} /** - * @brief Action {{ action.name }} parameter {{ param.name | upper }} + * @brief Action {% for action in param.paramActions %}{{ action }}{{ ", " if not loop.last else "" }}{% endfor %} parameter {{ param.name | upper }} * * @type {{ param.type }} * @flags CREATE_AND_SET {% if param.type == 'sai_uint16_t' %} * @isvlan false {% endif %} -{% if table.actions | length > 1 %} - * @condition SAI_{{ table.name | upper }}_ATTR_ACTION == SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }} -{% endif %} {% if param.type == 'sai_ip_address_t' %} * @default 0.0.0.0 {% elif param.type == 'sai_mac_t' %} @@ -176,6 +172,12 @@ typedef enum _sai_{{ table.name }}_attr_t * @default SAI_NULL_OBJECT_ID {% else %} * @default 0 +{% endif %} +{% if table.actions | length > 1 %} +{% if param.paramActions | length > 0 %} + * @validonly {% for action in param.paramActions %}SAI_{{ table.name | upper }}_ATTR_ACTION == SAI_{{ table.name | upper }}_ACTION_{{ action | upper }}{{ " or " if not loop.last else "" }}{% endfor %} + +{% endif %} {% endif %} */ {% if not ns.firstattr %} @@ -185,7 +187,6 @@ typedef enum _sai_{{ table.name }}_attr_t SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}, {% endif %} -{% endfor %} {% endfor %} {% if table.stages | length > 0 %} /** diff --git a/dash-pipeline/bmv2/dash_metadata.p4 b/dash-pipeline/bmv2/dash_metadata.p4 index e7dc169a2..f50151fe7 100644 --- a/dash-pipeline/bmv2/dash_metadata.p4 +++ b/dash-pipeline/bmv2/dash_metadata.p4 @@ -41,7 +41,9 @@ struct metadata_t { bit<16> inbound_vm_id; bit<8> appliance_id; bit<1> is_dst_ip_v6; + bit<1> is_lkup_dst_ip_v6; IPv4ORv6Address dst_ip_addr; + IPv4ORv6Address lkup_dst_ip_addr; conntrack_data_t conntrack_data; } diff --git a/dash-pipeline/bmv2/dash_outbound.p4 b/dash-pipeline/bmv2/dash_outbound.p4 index 2d14afe46..afa0c4df8 100644 --- a/dash-pipeline/bmv2/dash_outbound.p4 +++ b/dash-pipeline/bmv2/dash_outbound.p4 @@ -28,6 +28,22 @@ control outbound(inout headers_t hdr, meta.encap_data.dest_vnet_vni = dest_vnet_vni; } + action route_vnet_direct(bit<24> dest_vnet_vni, + bit<1> is_overlay_nh_ip_v4_or_v6, + IPv4ORv6Address overlay_nh_ip) { + meta.encap_data.dest_vnet_vni = dest_vnet_vni; + meta.lkup_dst_ip_addr = overlay_nh_ip; + meta.is_lkup_dst_ip_v6 = is_overlay_nh_ip_v4_or_v6; + } + + action route_direct() { + /* send to underlay router without any encap */ + } + + action drop() { + meta.dropped = true; + } + direct_counter(CounterType.packets_and_bytes) routing_counter; @name("routing|dash_vnet") @@ -40,7 +56,11 @@ control outbound(inout headers_t hdr, actions = { route_vnet; /* for expressroute - ecmp of overlay */ + route_vnet_direct; + route_direct; + drop; } + const default_action = drop; counters = routing_counter; } @@ -66,8 +86,8 @@ control outbound(inout headers_t hdr, key = { /* Flow for express route */ meta.encap_data.dest_vnet_vni : exact @name("meta.encap_data.dest_vnet_vni:dest_vni"); - meta.is_dst_ip_v6 : exact @name("meta.is_dst_ip_v6:v4_or_v6"); - meta.dst_ip_addr : exact @name("meta.dst_ip_addr:dip"); + meta.is_lkup_dst_ip_v6 : exact @name("meta.is_lkup_dst_ip_v6:v4_or_v6"); + meta.lkup_dst_ip_addr : exact @name("meta.lkup_dst_ip_addr:dip"); } actions = { @@ -101,6 +121,9 @@ control outbound(inout headers_t hdr, ConntrackIn.apply(hdr, meta); #endif // PNA_CONNTRACK + meta.lkup_dst_ip_addr = meta.dst_ip_addr; + meta.is_lkup_dst_ip_v6 = meta.is_dst_ip_v6; + switch (routing.apply().action_run) { route_vnet: { ca_to_pa.apply(); diff --git a/dash-pipeline/bmv2/dash_pipeline.p4 b/dash-pipeline/bmv2/dash_pipeline.p4 index e8a34cce2..82a93c361 100644 --- a/dash-pipeline/bmv2/dash_pipeline.p4 +++ b/dash-pipeline/bmv2/dash_pipeline.p4 @@ -228,8 +228,12 @@ control dash_ingress(inout headers_t hdr, 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 { + /* Send packet to port 1 by default if we reached the end of pipeline */ + standard_metadata.egress_spec = 1; + } } }