-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sai-gen] Refactor the templates of libsai implementation (#648)
Base on #647, refactor the templates of libsai implementation to make it more readable and maintainable. It replaces one single template `saiapi.cpp.j2` with several small templates under directory `SAI/templates/impls`. The changes will not change any generated cpp code for sai api implementation: ``` junhuazhai@junhuazhai-dev-vm:~/workspace/DASH/dash-pipeline$ diff -Nur -x '*.[od]' ~/DASH/dash-pipeline/SAI/lib/ SAI/lib junhuazhai@junhuazhai-dev-vm:~/workspace/DASH/dash-pipeline$ ```
- Loading branch information
Showing
12 changed files
with
609 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
{% if table.actions|length == 1 %} | ||
{% for name, action in table.actions.items() %} | ||
actionId = {{action.id}}; // {{name}} | ||
//expectedParams = {{ action.attr_params|length }}; | ||
{% endfor %} | ||
{% else %} | ||
// Search the action | ||
for (uint32_t i = 0; i < attr_count; i++) | ||
{ | ||
if (SAI_{{ api.name | upper }}_ATTR_ACTION == attr_list[i].id) | ||
{ | ||
switch(attr_list[i].value.s32) | ||
{ | ||
{% for name, action in table.actions.items() %} | ||
case {{ name }}: | ||
{ | ||
actionId = {{action.id}}; | ||
//expectedParams = {{ action.attr_params|length }}; | ||
break; | ||
} | ||
{% endfor %} | ||
default: | ||
DASH_LOG_ERROR("attribute value [%d] %d not supported yet", i, attr_list[i].value.s32); | ||
break; | ||
} | ||
// only one action | ||
break; | ||
} | ||
} | ||
{% endif %} | ||
action->set_action_id(actionId); | ||
|
||
for (uint32_t i = 0; i < attr_count; i++) | ||
{ | ||
auto *md = sai_metadata_get_attr_metadata((sai_object_type_t)SAI_OBJECT_TYPE_{{ api.name | upper }}, attr_list[i].id); | ||
|
||
const char* attrName = md ? md->attridname : "unknown"; | ||
|
||
switch(attr_list[i].id) | ||
{ | ||
{% set attr_id_list = [] %} | ||
{% for name, action in table.actions.items() %} | ||
{% for param_name, param in action.attr_params.items() %} | ||
{% if param_name in attr_id_list %}{% continue %}{% endif %} | ||
{% do attr_id_list.append( param_name ) %} | ||
{% if param.skipattr == 'true' %} | ||
{% else %} | ||
case {{ param_name }}: | ||
{ | ||
auto param = action->add_params(); | ||
param->set_param_id({{param.id}}); | ||
{{param.field}}SetVal(attr_list[i].value, param, {{param.bitwidth}}); | ||
//matchedParams++; | ||
{% if param.ip_is_v6_field_id != 0 %} | ||
{ | ||
// set ip_is_v6_field_id field | ||
auto param2 = action->add_params(); | ||
param2->set_param_id({{param.ip_is_v6_field_id}}); | ||
booldataSetVal((attr_list[i].value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, param2, 1); | ||
//matchedParams++; | ||
} | ||
{% endif %} | ||
break; | ||
} | ||
{% endif %} | ||
{% endfor %} | ||
{% endfor %} | ||
default: | ||
DASH_LOG_ERROR("attribute [%d] %d %s not supported yet", i, attr_list[i].id, attrName); | ||
break; | ||
} | ||
} | ||
|
24 changes: 24 additions & 0 deletions
24
dash-pipeline/SAI/templates/impls/p4_table_entry_match.cpp.j2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{% import 'templates/impls/p4_table_util.cpp.j2' as util %} | ||
{% for key in table['keys'] %} | ||
{% set value = 'tableEntry->' ~ key.name|lower %} | ||
{ | ||
auto mf = matchActionEntry->add_match(); | ||
mf->set_field_id({{key.id}}); | ||
{% if key.match_type == 'exact' %}{{ util.set_key_exact(key, value) }} | ||
{% elif key.match_type == 'lpm' %}{{ util.set_key_lpm(key, value) }} | ||
{% elif key.match_type == 'ternary' %}{{ util.set_key_ternary(key, value) }} | ||
{% elif key.match_type == 'optional' %}{{ util.set_key_optional(key, value) }} | ||
{% elif key.match_type == 'list' %}{{ util.set_key_list(key, value) }} | ||
{% elif key.match_type == 'range_list' %}{{ util.set_key_range_list(key, value) }} | ||
{% endif %} | ||
} | ||
{% if key.ip_is_v6_field_id != 0 %} | ||
{ | ||
// set ip_is_v6_field_id field | ||
auto mf = matchActionEntry->add_match(); | ||
mf->set_field_id({{key.ip_is_v6_field_id}}); | ||
auto mf_exact = mf->mutable_exact(); | ||
booldataSetVal(({{value}}.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, mf_exact, 1); | ||
} | ||
{% endif %} | ||
{% endfor %} |
66 changes: 66 additions & 0 deletions
66
dash-pipeline/SAI/templates/impls/p4_table_object_match.cpp.j2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
{% import 'templates/impls/p4_table_util.cpp.j2' as util %} | ||
{% for key in table['keys'] %} | ||
{% if key.is_object_key %} | ||
auto key_mf = matchActionEntry->add_match(); | ||
key_mf->set_field_id({{key.id}}); | ||
auto key_mf_exact = key_mf->mutable_exact(); | ||
// {{key.field}}SetVal(objId, key_mf_exact, {{key.bitwidth}}); | ||
{{key.field}}SetVal(static_cast<uint{{ key.bitwidth }}_t>(objId), key_mf_exact, {{ key.bitwidth }}); | ||
{% endif %} | ||
{% endfor %} | ||
|
||
// SAI object table with multiple P4 table keys | ||
// Copy P4 table keys from appropriate SAI attributes | ||
for (uint32_t i = 0; i < attr_count; i++) | ||
{ | ||
auto *md = sai_metadata_get_attr_metadata((sai_object_type_t)SAI_OBJECT_TYPE_{{ api.name | upper }}, attr_list[i].id); | ||
|
||
const char* attrName = md ? md->attridname : "unknown"; | ||
|
||
switch(attr_list[i].id) | ||
{ | ||
{% for key in table['keys'] %} | ||
{% if not key.is_object_key %} | ||
{% set value = 'attr_list[i].value' %} | ||
case SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}: | ||
{ | ||
auto mf = matchActionEntry->add_match(); | ||
mf->set_field_id({{key.id}}); | ||
{% filter indent(8, True) %} | ||
{% if key.match_type == 'exact' %}{{ util.set_key_in_attr_exact(key, value) }} | ||
{% elif key.match_type == 'lpm' %}{{ util.set_key_lpm(key, value) }} | ||
{% elif key.match_type == 'ternary' %}{{ util.set_key_in_attr_ternary(api, key, value) }} | ||
{% elif key.match_type == 'optional' %}{{ util.set_key_optional(key, value) }} | ||
{% elif key.match_type == 'list' %}{{ util.set_key_list(key, value) }} | ||
{% elif key.match_type == 'range_list' %}{{ util.set_key_range_list(key, value) }} | ||
{% endif %} | ||
{% endfilter %} | ||
{% if key.ip_is_v6_field_id != 0 %} | ||
{ | ||
// set ip_is_v6_field_id field | ||
auto mf = matchActionEntry->add_match(); | ||
mf->set_field_id({{key.ip_is_v6_field_id}}); | ||
auto mf_exact = mf->mutable_exact(); | ||
booldataSetVal(({{value}}.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, mf_exact, 1); | ||
} | ||
{% endif %} | ||
break; | ||
} | ||
{% endif%} | ||
{% endfor %} | ||
{% if table['keys'] | selectattr('match_type', 'ne', 'exact') | list | length > 0 %} | ||
{% if table['keys'] | selectattr('match_type', 'eq', 'lpm') | list | length == 0 %} | ||
// Table has non lpm ternary keys - add priority field | ||
case SAI_{{ api.name | upper }}_ATTR_PRIORITY: | ||
{ | ||
matchActionEntry->set_priority(attr_list[i].value.u32); | ||
break; | ||
} | ||
{% endif %} | ||
{% endif %} | ||
default: | ||
DASH_LOG_ERROR("attribute [%d] %d %s not supported yet", i, attr_list[i].id, attrName); | ||
break; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
{% macro set_key_exact(key, value) %} | ||
auto mf_exact = mf->mutable_exact(); | ||
{% if key.field in ['ipaddr','mac'] or key.bitwidth in [24] %} | ||
{{key.field}}SetVal({{value}}, mf_exact, {{key.bitwidth}}); | ||
{%- else %} | ||
{{key.field}}SetVal(static_cast<uint{{key.bitwidth}}_t>({{value}}), mf_exact, {{key.bitwidth}}); | ||
{%- endif %} | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_in_attr_exact(key, value) %} | ||
auto mf_exact = mf->mutable_exact(); | ||
{{key.field}}SetVal({{value}}, mf_exact, {{key.bitwidth}}); | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_lpm(key, value) %} | ||
{% if key.field == 'ipPrefix' %} | ||
if (getPrefixLength({{value}}) == 0) | ||
{ | ||
// https://github.com/p4lang/PI/blob/24e0a3c08c964e36d235973556b90e0ae922b894/proto/frontend/src/device_mgr.cpp#L2242-L2246 | ||
DASH_LOG_WARN("Invalid reprsentation of 'don't care' LPM match, omit match field instead of using a prefix length of 0"); | ||
return SAI_STATUS_SUCCESS; | ||
} | ||
{% endif %} | ||
auto mf_lpm = mf->mutable_lpm(); | ||
{{key.field}}SetVal({{value}}, mf_lpm, {{key.bitwidth}}); | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_in_attr_ternary(api, key, value) %} | ||
auto mf_ternary = mf->mutable_ternary(); | ||
{{key.field}}SetVal({{value}}, mf_ternary, {{key.bitwidth}}); | ||
auto mask = getMaskAttr(SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}_MASK, attr_count, attr_list); | ||
assert(mask && "SAI_{{ api.name | upper }}_ATTR_{{ key.name | upper }}_MASK isn't provided"); | ||
{{key.field}}SetMask(mask->value, mf_ternary, {{key.bitwidth}}); | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_ternary(key, value) %} | ||
auto mf_ternary = mf->mutable_ternary(); | ||
{{key.field}}SetVal({{value}}, mf_ternary, {{key.bitwidth}}); | ||
{{key.field}}SetMask({{value}}_mask, mf_ternary, {{key.bitwidth}}); | ||
matchActionEntry->set_priority(tableEntry->priority); | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_optional(key, value) %} | ||
auto mf_optional = mf->mutable_optional(); | ||
{{key.field}}SetVal({{value}}, mf_optional, {{key.bitwidth}}); | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_list(key, value) %} | ||
// BMv2 doesn't support "list" match type, and we are using "optional" match in v1model as our implementation. | ||
// Hence, here we only take the first item from the list and program it as optional match. | ||
assert({{value}}.{{key.field}}.count == 1 && "BMv2 only supports one item in list match type"); | ||
auto mf_optional = mf->mutable_optional(); | ||
sai_attribute_value_t attr_val; | ||
{% if key.field == 'ipprefixlist' %} | ||
attr_val.ipaddr.addr_family = {{value}}.ipprefixlist.list[0].addr_family; | ||
attr_val.ipaddr.addr = {{value}}.ipprefixlist.list[0].addr; | ||
ipaddrSetVal(attr_val, mf_optional, {{key.bitwidth}}); | ||
{%- else %} | ||
attr_val.{{ key.field | replace('list', '') }} = {{value}}.{{key.field}}.list[0]; | ||
{{ key.field | replace('list', '') }}SetVal(attr_val, mf_optional, {{key.bitwidth}}); | ||
{%- endif %} | ||
{%- endmacro -%} | ||
|
||
{% macro set_key_range_list(key, value) %} | ||
// BMv2 doesn't support "range_list" match type, and we are using "optional" match in v1model as our implementation. | ||
// Hence, here we only take the first item from the list and program the range start as optional match. | ||
assert(attr_list[i].value.{{key.field}}.count == 1 && "BMv2 only supports one item in list match type"); | ||
auto mf_optional = mf->mutable_optional(); | ||
{{ key.field | replace('rangelist', '') }}SetVal(attr_list[i].value.{{key.field}}.list[0].min, mf_optional, {{key.bitwidth}}); | ||
{%- endmacro -%} |
110 changes: 110 additions & 0 deletions
110
dash-pipeline/SAI/templates/impls/sai_api_func_bulk.cpp.j2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
{% if api.is_object == True %} | ||
static sai_status_t dash_sai_create_{{ api.name }}s( | ||
_In_ sai_object_id_t switch_id, | ||
_In_ uint32_t object_count, | ||
_In_ const uint32_t *attr_count, | ||
_In_ const sai_attribute_t **attr_list, | ||
_In_ sai_bulk_op_error_mode_t mode, | ||
_Out_ sai_object_id_t *object_id, | ||
_Out_ sai_status_t *object_statuses) | ||
{ | ||
DASH_LOG_ENTER(); | ||
return dash::DashSai::bulk_create_objects(dash_sai_create_{{ api.name }}, switch_id, object_count, attr_count, attr_list, mode, object_id, object_statuses); | ||
} | ||
|
||
static sai_status_t dash_sai_remove_{{ api.name }}s( | ||
_In_ uint32_t object_count, | ||
_In_ const sai_object_id_t *object_id, | ||
_In_ sai_bulk_op_error_mode_t mode, | ||
_Out_ sai_status_t *object_statuses) | ||
{ | ||
DASH_LOG_ENTER(); | ||
return dash::DashSai::bulk_remove_objects(dash_sai_remove_{{ api.name }}, object_count, object_id, mode, object_statuses); | ||
} | ||
{% else %} | ||
static sai_status_t dash_sai_create_{{ api.name | replace("entry", "entries") }}( | ||
_In_ uint32_t object_count, | ||
_In_ const sai_{{ api.name }}_t *{{ api.name }}, | ||
_In_ const uint32_t *attr_count, | ||
_In_ const sai_attribute_t **attr_list, | ||
_In_ sai_bulk_op_error_mode_t mode, | ||
_Out_ sai_status_t *object_statuses) | ||
{ | ||
DASH_LOG_ENTER(); | ||
|
||
sai_status_t agg_status = SAI_STATUS_SUCCESS; | ||
|
||
for (uint32_t i = 0; i < object_count; i++) | ||
{ | ||
object_statuses[i] = dash_sai_create_{{ api.name }}(&{{ api.name }}[i], attr_count[i], attr_list[i]); | ||
|
||
if (object_statuses[i] != SAI_STATUS_SUCCESS) | ||
{ | ||
agg_status = SAI_STATUS_FAILURE; | ||
} | ||
|
||
if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) | ||
{ | ||
return agg_status; | ||
} | ||
} | ||
|
||
return agg_status; | ||
} | ||
|
||
static sai_status_t dash_sai_remove_{{ api.name | replace("entry", "entries") }}( | ||
_In_ uint32_t object_count, | ||
_In_ const sai_{{ api.name }}_t *{{ api.name }}, | ||
_In_ sai_bulk_op_error_mode_t mode, | ||
_Out_ sai_status_t *object_statuses) | ||
{ | ||
DASH_LOG_ENTER(); | ||
|
||
sai_status_t agg_status = SAI_STATUS_SUCCESS; | ||
|
||
for (uint32_t i = 0; i < object_count; i++) | ||
{ | ||
object_statuses[i] = dash_sai_remove_{{ api.name }}(&{{ api.name }}[i]); | ||
|
||
if (object_statuses[i] != SAI_STATUS_SUCCESS) | ||
{ | ||
agg_status = SAI_STATUS_FAILURE; | ||
} | ||
|
||
if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) | ||
{ | ||
return agg_status; | ||
} | ||
} | ||
|
||
return agg_status; | ||
} | ||
{% if api.name == 'route_entry' %} | ||
|
||
static sai_status_t dash_sai_set_{{ api.name | replace("entry", "entries") }}_attribute( | ||
_In_ uint32_t object_count, | ||
_In_ const sai_route_entry_t *route_entry, | ||
_In_ const sai_attribute_t *attr_list, | ||
_In_ sai_bulk_op_error_mode_t mode, | ||
_Out_ sai_status_t *object_statuses) | ||
{ | ||
DASH_LOG_ENTER(); | ||
assert(0 && "sai_set_{{ api.name | replace("entry", "entries") }}_attribute NYI"); | ||
return SAI_STATUS_FAILURE; | ||
} | ||
|
||
static sai_status_t dash_sai_get_{{ api.name | replace("entry", "entries") }}_attribute( | ||
_In_ uint32_t object_count, | ||
_In_ const sai_route_entry_t *route_entry, | ||
_In_ const uint32_t *attr_count, | ||
_Inout_ sai_attribute_t **attr_list, | ||
_In_ sai_bulk_op_error_mode_t mode, | ||
_Out_ sai_status_t *object_statuses) | ||
{ | ||
DASH_LOG_ENTER(); | ||
assert(0 && "sai_get_{{ api.name | replace("entry", "entries") }}_attribute NYI"); | ||
return SAI_STATUS_FAILURE; | ||
} | ||
{% endif %} | ||
{% endif %} | ||
|
Oops, something went wrong.