Skip to content

Commit

Permalink
Adding support for metering
Browse files Browse the repository at this point in the history
- Metering P4 model changes in BMV2
- Changes to support the SAI api generation for metering tables
  • Loading branch information
vijasrin committed Jun 7, 2023
1 parent de161a2 commit f361496
Show file tree
Hide file tree
Showing 27 changed files with 441 additions and 86 deletions.
33 changes: 26 additions & 7 deletions dash-pipeline/SAI/sai_api_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
'sai_ip_address_t': 'ipaddr',
'sai_ip_addr_family_t': 'u32',
'sai_uint32_t': 'u32',
'sai_uint64_t': 'u64',
'sai_mac_t': 'mac'
}

Expand All @@ -54,13 +55,26 @@ def p4_annotation_to_sai_attr(p4rt, sai_attr):
sai_attr['type'] = kv['value']['stringValue']
elif kv['key'] == 'isresourcetype':
sai_attr['isresourcetype'] = kv['value']['stringValue']
elif kv['key'] == 'isreadonly':
sai_attr['isreadonly'] = kv['value']['stringValue']
elif kv['key'] == 'objects':
sai_attr['objectName'] = kv['value']['stringValue']
elif kv['key'] == 'skipattr':
sai_attr['skipattr'] = kv['value']['stringValue']
else:
print("Unknown attr annotation " + kv['key'])
exit(1)
sai_attr['field'] = sai_type_to_field[sai_attr['type']]

def p4_annotation_to_sai_table(p4rt, sai_table):
for anno in p4rt[STRUCTURED_ANNOTATIONS_TAG]:
if anno[NAME_TAG] == SAI_TAG:
for kv in anno[KV_PAIR_LIST_TAG][KV_PAIRS_TAG]:
if kv['key'] == 'isobject':
sai_table['is_object'] = kv['value']['stringValue']
if kv['key'] == 'ignoretable':
sai_table['ignore_table'] = kv['value']['stringValue']

def get_sai_key_type(key_size, key_header, key_field):
if key_size == 1:
return 'bool', "booldata"
Expand Down Expand Up @@ -252,7 +266,11 @@ def generate_sai_apis(program, ignore_tables):
sai_table_data[ACTIONS_TAG] = []
sai_table_data[ACTION_PARAMS_TAG] = []

if STRUCTURED_ANNOTATIONS_TAG in table['preamble']:
p4_annotation_to_sai_table(table['preamble'], sai_table_data)
table_control, table_name = table[PREAMBLE_TAG][NAME_TAG].split('.', 1)
if 'ignore_table' in sai_table_data.keys():
ignore_tables.append(table_name)
if table_name in ignore_tables:
continue

Expand Down Expand Up @@ -300,13 +318,14 @@ def generate_sai_apis(program, ignore_tables):
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'):
sai_table_data['is_object'] = 'true'
elif len(sai_table_data['keys']) > 5:
sai_table_data['is_object'] = 'true'
else:
sai_table_data['is_object'] = 'false'
sai_table_data['name'] = sai_table_data['name'] + '_entry'
if 'is_object' not in sai_table_data.keys():
if len(sai_table_data['keys']) == 1 and sai_table_data['keys'][0]['sai_key_name'].endswith(table_name.split('.')[-1] + '_id'):
sai_table_data['is_object'] = 'true'
elif len(sai_table_data['keys']) > 5:
sai_table_data['is_object'] = 'true'
else:
sai_table_data['is_object'] = 'false'
sai_table_data['name'] = sai_table_data['name'] + '_entry'

table_names.append(sai_table_data[NAME_TAG])
is_new_api = True
Expand Down
50 changes: 28 additions & 22 deletions dash-pipeline/SAI/templates/saiapi.cpp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ sai_status_t sai_create_{{ table.name }}(
// There shall be one and only one action_type
p4::v1::TableAction* entry = nullptr;
p4::v1::Action* action = nullptr;
auto expectedParams = 0;
auto matchedParams = 0;
//auto expectedParams = 0;
//auto matchedParams = 0;
sai_object_id_t objId = 0;
// Search the action
pi_p4_id_t actionId = 0;
Expand All @@ -58,8 +58,8 @@ sai_status_t sai_create_{{ table.name }}(
tableId = {{table.id}};
entry = matchActionEntry->mutable_action();
action = entry->mutable_action();
expectedParams = 0;
matchedParams = 0;
//expectedParams = 0;
//matchedParams = 0;
objId = 0;

matchActionEntry->set_table_id(tableId);
Expand Down Expand Up @@ -139,7 +139,7 @@ sai_status_t sai_create_{{ table.name }}(
{% if table.actions|length == 1 %}
{% for action in table.actions %}
actionId = {{action.id}}; // SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}
expectedParams = {{ action.params|length }};
//expectedParams = {{ action.params|length }};
{% endfor %}
{% else %}
// Search the action
Expand All @@ -150,7 +150,7 @@ sai_status_t sai_create_{{ table.name }}(
{% for action in table.actions %}
case SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}: {
actionId = {{action.id}};
expectedParams = {{ action.params|length }};
//expectedParams = {{ action.params|length }};
break;
}
{% endfor %}
Expand All @@ -165,31 +165,34 @@ sai_status_t sai_create_{{ table.name }}(
for (uint32_t i = 0; i < attr_count; i++) {
switch(attr_list[i].id) {
{% for param in table.actionParams %}
{% if param.skipattr == 'true' %}
{% else %}
case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: {
auto param = action->add_params();
param->set_param_id({{param.id}});
{{param.field}}SetVal(attr_list[i].value, param, {{param.bitwidth}});
matchedParams++;
//matchedParams++;
{% if 'v4_or_v6_id' in param %}
{
// set v4_or_v6 field
auto param = action->add_params();
param->set_param_id({{param.v4_or_v6_id}});
booldataSetVal((attr_list[i].value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, param, 1);
matchedParams++;
//matchedParams++;
}
{% endif %}
break;
}
{% endif %}
{% endfor %}
}
}

assert((matchedParams == expectedParams));
//assert((matchedParams == expectedParams));

if (matchedParams != expectedParams) {
goto ErrRet;
}
//if (matchedParams != expectedParams) {
// goto ErrRet;
//}
if (false == InsertInTable(matchActionEntry, &objId)) {
goto ErrRet;
}
Expand Down Expand Up @@ -284,8 +287,8 @@ sai_status_t sai_create_{{ table.name }}(
// There shall be one and only one action_type
auto entry = matchActionEntry->mutable_action();
auto action = entry->mutable_action();
auto expectedParams = 0;
auto matchedParams = 0;
//auto expectedParams = 0;
//auto matchedParams = 0;
pi_p4_id_t actionId;
grpc::StatusCode retCode;

Expand Down Expand Up @@ -327,7 +330,7 @@ sai_status_t sai_create_{{ table.name }}(
{% if table.actions|length == 1 %}
{% for action in table.actions %}
actionId = {{action.id}}; // SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}
expectedParams = {{ action.params|length }};
//expectedParams = {{ action.params|length }};
{% endfor %}
{% else %}
// Search the action
Expand All @@ -336,7 +339,7 @@ sai_status_t sai_create_{{ table.name }}(
{% for action in table.actions %}
case SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}: {
actionId = {{action.id}};
expectedParams = {{ action.params|length }};
//expectedParams = {{ action.params|length }};
break;
}
{% endfor %}
Expand All @@ -350,31 +353,34 @@ sai_status_t sai_create_{{ table.name }}(
for (uint32_t i = 0; i < attr_count; i++) {
switch(attr_list[i].id) {
{% for param in table.actionParams %}
{% if param.skipattr == 'true' %}
{% else %}
case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: {
auto param = action->add_params();
param->set_param_id({{param.id}});
{{param.field}}SetVal(attr_list[i].value, param, {{param.bitwidth}});
matchedParams++;
//matchedParams++;
{% if 'v4_or_v6_id' in param %}
{
// set v4_or_v6 field
auto param = action->add_params();
param->set_param_id({{param.v4_or_v6_id}});
booldataSetVal((attr_list[i].value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4) ? 0 : 1, param, 1);
matchedParams++;
//matchedParams++;
}
{% endif %}
break;
}
{% endif %}
{% endfor %}
}
}

assert((matchedParams == expectedParams));
//assert((matchedParams == expectedParams));

if (matchedParams != expectedParams) {
goto ErrRet;
}
//if (matchedParams != expectedParams) {
// goto ErrRet;
//}
// TODO: ternaly needs to set priority
retCode = MutateTableEntry(matchActionEntry, p4::v1::Update_Type_INSERT);
if (grpc::StatusCode::OK == retCode) {
Expand Down
11 changes: 11 additions & 0 deletions dash-pipeline/SAI/templates/saiapi.h.j2
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ typedef enum _sai_{{ table.name }}_attr_t
{% if table.is_object == 'true' %}
{% if table['keys'] | length > 1 %}
{% for key in table['keys'] %}
{% if key.isattribute != 'false' %}
/**
* @brief {{ key.match_type | capitalize | replace('Lpm', 'LPM') }} matched key {{ key.sai_key_name }}
*
Expand Down Expand Up @@ -149,16 +150,23 @@ typedef enum _sai_{{ table.name }}_attr_t
*/
SAI_{{ table.name | upper }}_ATTR_{{ key.sai_key_name | upper }}_MASK,

{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% for param in table.actionParams %}
{% if param.skipattr == 'true' %}
{% else %}
/**
* @brief Action {% for action in param.paramActions %}{{ action }}{{ ", " if not loop.last else "" }}{% endfor %} parameter {{ param.name | upper }}
*
* @type {{ param.type }}
{% if param.isreadonly == 'true' %}
* @flags READ_ONLY
{% else %}
* @flags CREATE_AND_SET
{% endif %}
{% if param.type == 'sai_uint16_t' %}
* @isvlan false
{% endif %}
Expand All @@ -177,8 +185,10 @@ typedef enum _sai_{{ table.name }}_attr_t
{% elif param.field == 's32' %}
* @default {{ param.default }}
{% else %}
{% if param.isreadonly != 'true' %}
* @default 0
{% endif %}
{% 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 %}
Expand All @@ -196,6 +206,7 @@ typedef enum _sai_{{ table.name }}_attr_t
SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }},
{% endif %}

{% endif %}
{% endfor %}
{% if table.with_counters == 'true' %}
/**
Expand Down
21 changes: 21 additions & 0 deletions dash-pipeline/SAI/templates/utils.h.j2
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,27 @@ void ipaddrSetVal(const sai_ip_address_t &value, T &t, int bits = -1){
}
}

template<typename T>
void ipaddrSetMask(const sai_attribute_value_t &value, T &t, int bits = -1){
ipaddrSetMask(value.ipaddr, t);
}

template<typename T>
void ipaddrSetMask(const sai_ip_address_t &value, T &t, int bits = -1){
switch(value.addr_family) {
case SAI_IP_ADDR_FAMILY_IPV4: {
uint32_t mask = value.addr.ip4;
t->set_mask(&mask, 4);
}
break;
case SAI_IP_ADDR_FAMILY_IPV6: {
t->set_mask(const_cast<uint8_t*>(&value.addr.ip6[0]), 16);
}
break;
default: assert(0 && "unrecognzed value.ipaddr.addr_family");
}
}

template<typename T>
void macSetVal(const sai_attribute_value_t &value, T &t, int bits = -1){
t->set_value(const_cast<uint8_t*>(&value.mac[0]), 6);
Expand Down
8 changes: 8 additions & 0 deletions dash-pipeline/bmv2/dash_metadata.p4
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ struct metadata_t {
bit<16> stage3_dash_acl_group_id;
bit<16> stage4_dash_acl_group_id;
bit<16> stage5_dash_acl_group_id;
bit<1> meter_policy_en;
bit<1> mapping_meter_class_override;
bit<16> meter_policy_id;
bit<16> policy_meter_class;
bit<16> route_meter_class;
bit<16> mapping_meter_class;
bit<16> meter_class;
bit<32> meter_bucket_index;
tag_map_t src_tag_map;
tag_map_t dst_tag_map;
}
Expand Down
30 changes: 25 additions & 5 deletions dash-pipeline/bmv2/dash_outbound.p4
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,32 @@
control outbound(inout headers_t hdr,
inout metadata_t meta)
{
action route_vnet(bit<16> dst_vnet_id) {
action set_route_meter_attrs(bit<1> meter_policy_en,
bit<16> meter_class) {
meta.meter_policy_en = meter_policy_en;
meta.route_meter_class = meter_class;
}
action route_vnet(bit<16> dst_vnet_id,
bit<1> meter_policy_en,
bit<16> meter_class) {
meta.dst_vnet_id = dst_vnet_id;
set_route_meter_attrs(meter_policy_en, meter_class);
}

action route_vnet_direct(bit<16> dst_vnet_id,
bit<1> is_overlay_ip_v4_or_v6,
IPv4ORv6Address overlay_ip) {
IPv4ORv6Address overlay_ip,
bit<1> meter_policy_en,
bit<16> meter_class) {
meta.dst_vnet_id = dst_vnet_id;
meta.lkup_dst_ip_addr = overlay_ip;
meta.is_lkup_dst_ip_v6 = is_overlay_ip_v4_or_v6;
set_route_meter_attrs(meter_policy_en, meter_class);
}

action route_direct() {
action route_direct(bit<1> meter_policy_en,
bit<16> meter_class) {
set_route_meter_attrs(meter_policy_en, meter_class);
/* send to underlay router without any encap */
}

Expand All @@ -42,7 +55,9 @@ control outbound(inout headers_t hdr,
bit<1> is_underlay_sip_v4_or_v6,
IPv4ORv6Address underlay_sip,
dash_encapsulation_t dash_encapsulation,
bit<24> tunnel_key) {
bit<24> tunnel_key,
bit<1> meter_policy_en,
bit<16> meter_class) {
/* Assume the overlay addresses provided are always IPv6 and the original are IPv4 */
/* assert(is_overlay_dip_v4_or_v6 == 1 && is_overlay_sip_v4_or_v6 == 1);
assert(is_overlay_dip_mask_v4_or_v6 == 1 && is_overlay_sip_mask_v4_or_v6 == 1);
Expand All @@ -62,6 +77,7 @@ control outbound(inout headers_t hdr,
meta.encap_data.overlay_dmac = hdr.ethernet.dst_addr;
meta.encap_data.dash_encapsulation = dash_encapsulation;
meta.encap_data.service_tunnel_key = tunnel_key;
set_route_meter_attrs(meter_policy_en, meter_class);
}

#ifdef TARGET_BMV2_V1MODEL
Expand Down Expand Up @@ -104,11 +120,15 @@ control outbound(inout headers_t hdr,

action set_tunnel_mapping(IPv4Address underlay_dip,
EthernetAddress overlay_dmac,
bit<1> use_dst_vnet_vni) {
bit<1> use_dst_vnet_vni,
bit<16> meter_class,
bit<1> meter_class_override) {
if (use_dst_vnet_vni == 1)
meta.vnet_id = meta.dst_vnet_id;
meta.encap_data.overlay_dmac = overlay_dmac;
meta.encap_data.underlay_dip = underlay_dip;
meta.mapping_meter_class = meter_class;
meta.mapping_meter_class_override = meter_class_override;
}

#ifdef TARGET_BMV2_V1MODEL
Expand Down
Loading

0 comments on commit f361496

Please sign in to comment.