Skip to content

Commit

Permalink
Add P4 meta in SAI spec for lib generation, support merge SAI spec.
Browse files Browse the repository at this point in the history
  • Loading branch information
r12f committed Jun 2, 2024
1 parent cd0e22d commit 6b24497
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 27 deletions.
4 changes: 2 additions & 2 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,13 @@ def generate_counter_sai_attributes(self) -> "Iterator[DashP4Counter]":
#
# Functions for generating SAI specs.
#
def _get_sai_name(self, table_name: str) -> str:
def get_sai_name(self, table_name: str) -> str:
if self.attr_type == "stats":
return f"SAI_{table_name.upper()}_STAT_{self.name.upper()}"

return f"SAI_{table_name.upper()}_{self.name.upper()}"

def _get_sai_description(self, table_name: str):
def get_sai_description(self, table_name: str):
if self.attr_type == "stats":
return f"DASH {table_name.upper()} {self.name.upper()} stat count"

Expand Down
29 changes: 24 additions & 5 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .dash_p4_table_action_param import *
from .dash_p4_table_key import *
from .dash_p4_table_action import *
from ..sai_spec import SaiApi, SaiStruct, SaiEnum, SaiEnumMember, SaiAttribute
from ..sai_spec import SaiApi, SaiStruct, SaiEnum, SaiEnumMember, SaiAttribute, SaiApiP4MetaAction, SaiApiP4MetaTable


@dash_p4rt_parser
Expand Down Expand Up @@ -264,6 +264,7 @@ def __build_sai_attributes_after_parsing(self):
#
def to_sai(self) -> SaiApi:
sai_api = SaiApi(self.name, "", self.is_object != "false")
sai_api.p4_meta.tables.append(SaiApiP4MetaTable(self.id))

self.create_sai_action_enum(sai_api)
self.create_sai_structs(sai_api)
Expand All @@ -276,19 +277,36 @@ def create_sai_action_enum(self, sai_api: SaiApi) -> None:
# If the table represents an SAI object, it should not have an action enum.
# If the table has only 1 action, we don't need to create the action enum.
if len(self.actions) <= 1 and self.is_object != "false":
# We still need to create the p4 meta action here for generating default action code in libsai.
if len(self.actions) == 1:
sai_api.p4_meta.tables[0].actions["default"] = SaiApiP4MetaAction("default", self.actions[0].id)
return

action_enum_member_value = 0
action_enum_members: List[SaiEnumMember] = []
for action in self.actions:
action_enum_member_name = f"SAI_{self.name.upper()}_ACTION_{action.name.upper()}"

action_enum_members.append(
SaiEnumMember(
name=f"SAI_{self.name.upper()}_ACTION_{action.name.upper()}",
name=action_enum_member_name,
description="",
value=str(action_enum_member_value),
)
)

p4_meta_action = SaiApiP4MetaAction(
name=action_enum_member_name,
id=action.id,
)

for action_param in action.params:
p4_meta_action.attr_param_id[action_param.get_sai_name(self.name)] = action_param.id

sai_api.p4_meta.tables[0].actions[action_enum_member_name] = p4_meta_action

action_enum_member_value += 1

action_enum_type_name = f"sai_{self.name.lower()}_action_t"

action_enum = SaiEnum(
Expand All @@ -307,6 +325,7 @@ def create_sai_action_enum(self, sai_api: SaiApi) -> None:
)
sai_api.attributes.append(sai_attr_action)


def create_sai_structs(self, sai_api: SaiApi) -> None:
# The entry struct is only needed for non-object tables.
if self.is_object != "false":
Expand All @@ -329,9 +348,9 @@ def create_sai_stats(self, sai_api: SaiApi) -> None:
]

def create_sai_attributes(self, sai_api: SaiApi) -> None:
sai_api.attributes.extend(
[attr.to_sai_attribute(self.name) for attr in self.sai_attributes if attr.skipattr != "true"]
)
for attr in self.sai_attributes:
if attr.skipattr != "true":
sai_api.attributes.append(attr.to_sai_attribute(self.name))

# If the table has an counter attached, we need to create a counter attribute for it.
# The counter attribute only counts that packets that hits any entry, but not the packet that misses all entries.
Expand Down
12 changes: 6 additions & 6 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ def set_sai_type(self, sai_type_info: SAITypeInfo) -> None:
# Functions for generating SAI specs.
#
def to_sai_struct_entry(self, table_name: str) -> SaiStructEntry:
name = self._get_sai_name(table_name)
description = self._get_sai_description(table_name)
name = self.get_sai_name(table_name)
description = self.get_sai_description(table_name)
object_name = f"SAI_OBJECT_TYPE_{self.object_name.upper()}" if self.object_name else None

return SaiStructEntry(
Expand All @@ -108,8 +108,8 @@ def to_sai_struct_entry(self, table_name: str) -> SaiStructEntry:
)

def to_sai_attribute(self, table_name: str) -> SaiAttribute:
name = self._get_sai_name(table_name)
description = self._get_sai_description(table_name)
name = self.get_sai_name(table_name)
description = self.get_sai_description(table_name)

default_value = None if self.isreadonly == "true" else self.default
object_name = f"SAI_OBJECT_TYPE_{self.object_name.upper()}" if self.object_name else None
Expand All @@ -129,8 +129,8 @@ def to_sai_attribute(self, table_name: str) -> SaiAttribute:
valid_only = self.validonly,
)

def _get_sai_name(self, table_name: str) -> str:
def get_sai_name(self, table_name: str) -> str:
return f"SAI_{table_name.upper()}_{self.name.upper()}"

def _get_sai_description(self, table_name: str):
def get_sai_description(self, table_name: str):
return f"Action parameter {self.name.upper()}"
25 changes: 14 additions & 11 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table_group.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import List, Optional
from .common import *
from .dash_p4_table import DashP4Table
from ..sai_spec import SaiApiGroup
from ..sai_spec import SaiApiGroup, SaiApi


class DashP4TableGroup(DashP4Object):
Expand All @@ -25,20 +25,23 @@ def add_table(self, table: DashP4Table) -> None:
self.tables.append(table)

def post_parsing_process(self, all_table_names: List[str]) -> None:
self.__ignore_duplicated_tables_in_headers()

for table in self.tables:
table.post_parsing_process(all_table_names)

def __ignore_duplicated_tables_in_headers(self) -> None:
table_names = set()

def to_sai(self) -> SaiApiGroup:
sai_api_list: List[SaiApi] = []
sai_api_map: Dict[str, SaiApi] = {}

for table in self.tables:
if table.name in table_names:
sai_api = table.to_sai()

if table.name in sai_api_map:
table.ignored_in_header = True
table_names.add(table.name)
sai_api_map[table.name].p4_meta.tables.extend(sai_api.p4_meta.tables)
else:
sai_api_map[table.name] = sai_api
sai_api_list.append(sai_api)

def to_sai(self) -> SaiApiGroup:
sai_api_group = SaiApiGroup(self.app_name, "")
sai_api_group.sai_apis = [table.to_sai() for table in self.tables if not table.ignored_in_header]
return sai_api_group
sai_api_group.sai_apis = sai_api_list
return sai_api_group
4 changes: 2 additions & 2 deletions dash-pipeline/SAI/utils/dash_p4/dash_p4_table_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ def parse_p4rt(self, p4rt_table_key: Dict[str, Any]) -> None:
#
# Functions for generating SAI specs.
#
def _get_sai_name(self, table_name: str) -> str:
def get_sai_name(self, table_name: str) -> str:
if self.is_entry_key:
return self.name

return f"SAI_{table_name.upper()}_{self.name.upper()}"

def _get_sai_description(self, table_name: str):
def get_sai_description(self, table_name: str):
return f"{self.match_type.capitalize()} matched key {self.name}"
4 changes: 3 additions & 1 deletion dash-pipeline/SAI/utils/dash_p4/dash_sai_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,14 @@ def post_parsing_process(self) -> None:
#
def to_sai(self) -> SaiSpec:
sai_spec = SaiSpec()
sai_spec.api_groups = [api_group.to_sai() for api_group in self.table_groups]

self.create_sai_api_types(sai_spec)
self.create_sai_object_types(sai_spec)
self.create_sai_object_entries(sai_spec)
self.create_sai_enums(sai_spec)
self.create_sai_port_counters(sai_spec.port_extenstion)
sai_spec.api_groups = [api_group.to_sai() for api_group in self.table_groups]

return sai_spec

def create_sai_api_types(self, sai_spec: SaiSpec):
Expand Down
1 change: 1 addition & 0 deletions dash-pipeline/SAI/utils/sai_spec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
from .sai_struct import SaiStruct
from .sai_struct_entry import SaiStructEntry
from .sai_attribute import SaiAttribute
from .sai_api_p4_meta import SaiApiP4Meta, SaiApiP4MetaTable, SaiApiP4MetaAction
6 changes: 6 additions & 0 deletions dash-pipeline/SAI/utils/sai_spec/sai_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .sai_attribute import SaiAttribute
from .sai_enum import SaiEnum
from .sai_struct import SaiStruct
from .sai_api_p4_meta import SaiApiP4Meta
from . import sai_spec_utils


Expand All @@ -18,6 +19,7 @@ def __init__(self, name: str, description: str, is_object: bool = False):
self.structs: List[SaiStruct] = []
self.attributes: List[SaiAttribute] = []
self.stats: List[SaiAttribute] = []
self.p4_meta: SaiApiP4Meta = SaiApiP4Meta()

def merge(self, other: "SaiCommon"):
super().merge(other)
Expand All @@ -27,3 +29,7 @@ def merge(self, other: "SaiCommon"):
sai_spec_utils.merge_sai_common_lists(self.structs, other.structs)
sai_spec_utils.merge_sai_common_lists(self.attributes, other.attributes)
sai_spec_utils.merge_sai_common_lists(self.stats, other.stats)

# The P4 meta can be merged by replacing the old one, since it doesn't affect the ABI,
# and the new one is always more up-to-date.
self.p4_meta = other.p4_meta

0 comments on commit 6b24497

Please sign in to comment.