Skip to content

Commit

Permalink
ynl: support directional specs in ynl-gen-c.py
Browse files Browse the repository at this point in the history
The intent is to generate ethtool uapi headers. For now, some of the
things are hard-coded:
- <FAMILY>_MSG_{USER,KERNEL}_MAX
- the split between USER and KERNEL messages

Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20241204155549.641348-4-sdf@fomichev.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Stanislav Fomichev authored and Jakub Kicinski committed Dec 5, 2024
1 parent 8c843ec commit 56881d0
Showing 1 changed file with 87 additions and 31 deletions.
118 changes: 87 additions & 31 deletions tools/net/ynl/ynl-gen-c.py
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,87 @@ def uapi_enum_start(family, cw, obj, ckey='', enum_name='enum-name'):
cw.block_start(line=start_line)


def render_uapi_unified(family, cw, max_by_define, separate_ntf):
max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX"))
cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX"))
max_value = f"({cnt_name} - 1)"

uapi_enum_start(family, cw, family['operations'], 'enum-name')
val = 0
for op in family.msgs.values():
if separate_ntf and ('notify' in op or 'event' in op):
continue

suffix = ','
if op.value != val:
suffix = f" = {op.value},"
val = op.value
cw.p(op.enum_name + suffix)
val += 1
cw.nl()
cw.p(cnt_name + ('' if max_by_define else ','))
if not max_by_define:
cw.p(f"{max_name} = {max_value}")
cw.block_end(line=';')
if max_by_define:
cw.p(f"#define {max_name} {max_value}")
cw.nl()


def render_uapi_directional(family, cw, max_by_define):
max_name = f"{family.op_prefix}USER_MAX"
cnt_name = f"__{family.op_prefix}USER_CNT"
max_value = f"({cnt_name} - 1)"

cw.block_start(line='enum')
cw.p(c_upper(f'{family.name}_MSG_USER_NONE = 0,'))
val = 0
for op in family.msgs.values():
if 'do' in op and 'event' not in op:
suffix = ','
if op.value and op.value != val:
suffix = f" = {op.value},"
val = op.value
cw.p(op.enum_name + suffix)
val += 1
cw.nl()
cw.p(cnt_name + ('' if max_by_define else ','))
if not max_by_define:
cw.p(f"{max_name} = {max_value}")
cw.block_end(line=';')
if max_by_define:
cw.p(f"#define {max_name} {max_value}")
cw.nl()

max_name = f"{family.op_prefix}KERNEL_MAX"
cnt_name = f"__{family.op_prefix}KERNEL_CNT"
max_value = f"({cnt_name} - 1)"

cw.block_start(line='enum')
cw.p(c_upper(f'{family.name}_MSG_KERNEL_NONE = 0,'))
val = 0
for op in family.msgs.values():
if ('do' in op and 'reply' in op['do']) or 'notify' in op or 'event' in op:
enum_name = op.enum_name
if 'event' not in op and 'notify' not in op:
enum_name = f'{enum_name}_REPLY'

suffix = ','
if op.value and op.value != val:
suffix = f" = {op.value},"
val = op.value
cw.p(enum_name + suffix)
val += 1
cw.nl()
cw.p(cnt_name + ('' if max_by_define else ','))
if not max_by_define:
cw.p(f"{max_name} = {max_value}")
cw.block_end(line=';')
if max_by_define:
cw.p(f"#define {max_name} {max_value}")
cw.nl()


def render_uapi(family, cw):
hdr_prot = f"_UAPI_LINUX_{c_upper(family.uapi_header_name)}_H"
hdr_prot = hdr_prot.replace('/', '_')
Expand Down Expand Up @@ -2523,30 +2604,12 @@ def render_uapi(family, cw):
# Commands
separate_ntf = 'async-prefix' in family['operations']

max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX"))
cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX"))
max_value = f"({cnt_name} - 1)"

uapi_enum_start(family, cw, family['operations'], 'enum-name')
val = 0
for op in family.msgs.values():
if separate_ntf and ('notify' in op or 'event' in op):
continue

suffix = ','
if op.value != val:
suffix = f" = {op.value},"
val = op.value
cw.p(op.enum_name + suffix)
val += 1
cw.nl()
cw.p(cnt_name + ('' if max_by_define else ','))
if not max_by_define:
cw.p(f"{max_name} = {max_value}")
cw.block_end(line=';')
if max_by_define:
cw.p(f"#define {max_name} {max_value}")
cw.nl()
if family.msg_id_model == 'unified':
render_uapi_unified(family, cw, max_by_define, separate_ntf)
elif family.msg_id_model == 'directional':
render_uapi_directional(family, cw, max_by_define)
else:
raise Exception(f'Unsupported message enum-model {family.msg_id_model}')

if separate_ntf:
uapi_enum_start(family, cw, family['operations'], enum_name='async-enum')
Expand Down Expand Up @@ -2670,13 +2733,6 @@ def main():
os.sys.exit(1)
return

supported_models = ['unified']
if args.mode in ['user', 'kernel']:
supported_models += ['directional']
if parsed.msg_id_model not in supported_models:
print(f'Message enum-model {parsed.msg_id_model} not supported for {args.mode} generation')
os.sys.exit(1)

cw = CodeWriter(BaseNlLib(), args.out_file, overwrite=(not args.cmp_out))

_, spec_kernel = find_kernel_root(args.spec)
Expand Down

0 comments on commit 56881d0

Please sign in to comment.