Commit c554520f authored by Paolo Abeni's avatar Paolo Abeni

Merge branch 'netlink-protocol-specs'

Jakub Kicinski says:

====================
Netlink protocol specs

I think the Netlink proto specs are far along enough to merge.
Filling in all attribute types and quirks will be an ongoing
effort but we have enough to cover FOU so it's somewhat complete.

I fully intend to continue polishing the code but at the same
time I'd like to start helping others base their work on the
specs (e.g. DPLL) and need to start working on some new families
myself.

That's the progress / motivation for merging. The RFC [1] has more
of a high level blurb, plus I created a lot of documentation, I'm
not going to repeat it here. There was also the talk at LPC [2].

[1] https://lore.kernel.org/all/20220811022304.583300-1-kuba@kernel.org/
[2] https://youtu.be/9QkXIQXkaQk?t=2562
v2: https://lore.kernel.org/all/20220930023418.1346263-1-kuba@kernel.org/
v3: https://lore.kernel.org/all/20230119003613.111778-1-kuba@kernel.org/1

v4:
 - spec improvements (patch 2)
 - Python cleanup (patch 3)
 - rename auto-gen files and use the right comment style
====================

Link: https://lore.kernel.org/r/20230120175041.342573-1-kuba@kernel.orgSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents d961bee4 e4b48ed4
......@@ -127,6 +127,7 @@ Documents that don't fit elsewhere or which have yet to be categorized.
:maxdepth: 1
librs
netlink
.. only:: subproject and html
......
.. SPDX-License-Identifier: BSD-3-Clause
.. _kernel_netlink:
===================================
Netlink notes for kernel developers
===================================
General guidance
================
Attribute enums
---------------
Older families often define "null" attributes and commands with value
of ``0`` and named ``unspec``. This is supported (``type: unused``)
but should be avoided in new families. The ``unspec`` enum values are
not used in practice, so just set the value of the first attribute to ``1``.
Message enums
-------------
Use the same command IDs for requests and replies. This makes it easier
to match them up, and we have plenty of ID space.
Use separate command IDs for notifications. This makes it easier to
sort the notifications from replies (and present them to the user
application via a different API than replies).
Answer requests
---------------
Older families do not reply to all of the commands, especially NEW / ADD
commands. User only gets information whether the operation succeeded or
not via the ACK. Try to find useful data to return. Once the command is
added whether it replies with a full message or only an ACK is uAPI and
cannot be changed. It's better to err on the side of replying.
Specifically NEW and ADD commands should reply with information identifying
the created object such as the allocated object's ID (without having to
resort to using ``NLM_F_ECHO``).
NLM_F_ECHO
----------
Make sure to pass the request info to genl_notify() to allow ``NLM_F_ECHO``
to take effect. This is useful for programs that need precise feedback
from the kernel (for example for logging purposes).
Support dump consistency
------------------------
If iterating over objects during dump may skip over objects or repeat
them - make sure to report dump inconsistency with ``NLM_F_DUMP_INTR``.
This is usually implemented by maintaining a generation id for the
structure and recording it in the ``seq`` member of struct netlink_callback.
Netlink specification
=====================
Documentation of the Netlink specification parts which are only relevant
to the kernel space.
Globals
-------
kernel-policy
~~~~~~~~~~~~~
Defines if the kernel validation policy is per operation (``per-op``)
or for the entire family (``global``). New families should use ``per-op``
(default) to be able to narrow down the attributes accepted by a specific
command.
checks
------
Documentation for the ``checks`` sub-sections of attribute specs.
unterminated-ok
~~~~~~~~~~~~~~~
Accept strings without the null-termination (for legacy families only).
Switches from the ``NLA_NUL_STRING`` to ``NLA_STRING`` policy type.
max-len
~~~~~~~
Defines max length for a binary or string attribute (corresponding
to the ``len`` member of struct nla_policy). For string attributes terminating
null character is not counted towards ``max-len``.
The field may either be a literal integer value or a name of a defined
constant. String types may reduce the constant by one
(i.e. specify ``max-len: CONST - 1``) to reserve space for the terminating
character so implementations should recognize such pattern.
min-len
~~~~~~~
Similar to ``max-len`` but defines minimum length.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
name: fou
protocol: genetlink-legacy
doc: |
Foo-over-UDP.
c-family-name: fou-genl-name
c-version-name: fou-genl-version
max-by-define: true
kernel-policy: global
definitions:
-
type: enum
name: encap_type
name-prefix: fou-encap-
enum-name:
entries: [ unspec, direct, gue ]
attribute-sets:
-
name: fou
name-prefix: fou-attr-
attributes:
-
name: unspec
type: unused
-
name: port
type: u16
byte-order: big-endian
-
name: af
type: u8
-
name: ipproto
type: u8
-
name: type
type: u8
-
name: remcsum_nopartial
type: flag
-
name: local_v4
type: u32
-
name: local_v6
type: binary
checks:
min-len: 16
-
name: peer_v4
type: u32
-
name: peer_v6
type: binary
checks:
min-len: 16
-
name: peer_port
type: u16
byte-order: big-endian
-
name: ifindex
type: s32
operations:
list:
-
name: unspec
doc: unused
-
name: add
doc: Add port.
attribute-set: fou
dont-validate: [ strict, dump ]
flags: [ admin-perm ]
do:
request: &all_attrs
attributes:
- port
- ipproto
- type
- remcsum_nopartial
- local_v4
- peer_v4
- local_v6
- peer_v6
- peer_port
- ifindex
-
name: del
doc: Delete port.
attribute-set: fou
dont-validate: [ strict, dump ]
flags: [ admin-perm ]
do:
request: &select_attrs
attributes:
- af
- ifindex
- port
- peer_port
- local_v4
- peer_v4
- local_v6
- peer_v6
-
name: get
doc: Get tunnel info.
attribute-set: fou
dont-validate: [ strict, dump ]
do:
request: *select_attrs
reply: *all_attrs
dump:
reply: *all_attrs
.. SPDX-License-Identifier: BSD-3-Clause
==============================
Netlink spec C code generation
==============================
This document describes how Netlink specifications are used to render
C code (uAPI, policies etc.). It also defines the additional properties
allowed in older families by the ``genetlink-c`` protocol level,
to control the naming.
For brevity this document refers to ``name`` properties of various
objects by the object type. For example ``$attr`` is the value
of ``name`` in an attribute, and ``$family`` is the name of the
family (the global ``name`` property).
The upper case is used to denote literal values, e.g. ``$family-CMD``
means the concatenation of ``$family``, a dash character, and the literal
``CMD``.
The names of ``#defines`` and enum values are always converted to upper case,
and with dashes (``-``) replaced by underscores (``_``).
If the constructed name is a C keyword, an extra underscore is
appended (``do`` -> ``do_``).
Globals
=======
``c-family-name`` controls the name of the ``#define`` for the family
name, default is ``$family-FAMILY-NAME``.
``c-version-name`` controls the name of the ``#define`` for the version
of the family, default is ``$family-FAMILY-VERSION``.
``max-by-define`` selects if max values for enums are defined as a
``#define`` rather than inside the enum.
Definitions
===========
Constants
---------
Every constant is rendered as a ``#define``.
The name of the constant is ``$family-$constant`` and the value
is rendered as a string or integer according to its type in the spec.
Enums and flags
---------------
Enums are named ``$family-$enum``. The full name can be set directly
or suppressed by specifying the ``enum-name`` property.
Default entry name is ``$family-$enum-$entry``.
If ``name-prefix`` is specified it replaces the ``$family-$enum``
portion of the entry name.
Boolean ``render-max`` controls creation of the max values
(which are enabled by default for attribute enums).
Attributes
==========
Each attribute set (excluding fractional sets) is rendered as an enum.
Attribute enums are traditionally unnamed in netlink headers.
If naming is desired ``enum-name`` can be used to specify the name.
The default attribute name prefix is ``$family-A`` if the name of the set
is the same as the name of the family and ``$family-A-$set`` if the names
differ. The prefix can be overridden by the ``name-prefix`` property of a set.
The rest of the section will refer to the prefix as ``$pfx``.
Attributes are named ``$pfx-$attribute``.
Attribute enums end with two special values ``__$pfx-MAX`` and ``$pfx-MAX``
which are used for sizing attribute tables.
These two names can be specified directly with the ``attr-cnt-name``
and ``attr-max-name`` properties respectively.
If ``max-by-define`` is set to ``true`` at the global level ``attr-max-name``
will be specified as a ``#define`` rather than an enum value.
Operations
==========
Operations are named ``$family-CMD-$operation``.
If ``name-prefix`` is specified it replaces the ``$family-CMD``
portion of the name.
Similarly to attribute enums operation enums end with special count and max
attributes. For operations those attributes can be renamed with
``cmd-cnt-name`` and ``cmd-max-name``. Max will be a define if ``max-by-define``
is ``true``.
Multicast groups
================
Each multicast group gets a define rendered into the kernel uAPI header.
The name of the define is ``$family-MCGRP-$group``, and can be overwritten
with the ``c-define-name`` property.
Code generation
===============
uAPI header is assumed to come from ``<linux/$family.h>`` in the default header
search path. It can be changed using the ``uapi-header`` global property.
.. SPDX-License-Identifier: BSD-3-Clause
=================================================================
Netlink specification support for legacy Generic Netlink families
=================================================================
This document describes the many additional quirks and properties
required to describe older Generic Netlink families which form
the ``genetlink-legacy`` protocol level.
The spec is a work in progress, some of the quirks are just documented
for future reference.
Specification (defined)
=======================
Attribute type nests
--------------------
New Netlink families should use ``multi-attr`` to define arrays.
Older families (e.g. ``genetlink`` control family) attempted to
define array types reusing attribute type to carry information.
For reference the ``multi-attr`` array may look like this::
[ARRAY-ATTR]
[INDEX (optionally)]
[MEMBER1]
[MEMBER2]
[SOME-OTHER-ATTR]
[ARRAY-ATTR]
[INDEX (optionally)]
[MEMBER1]
[MEMBER2]
where ``ARRAY-ATTR`` is the array entry type.
array-nest
~~~~~~~~~~
``array-nest`` creates the following structure::
[SOME-OTHER-ATTR]
[ARRAY-ATTR]
[ENTRY]
[MEMBER1]
[MEMBER2]
[ENTRY]
[MEMBER1]
[MEMBER2]
It wraps the entire array in an extra attribute (hence limiting its size
to 64kB). The ``ENTRY`` nests are special and have the index of the entry
as their type instead of normal attribute type.
type-value
~~~~~~~~~~
``type-value`` is a construct which uses attribute types to carry
information about a single object (often used when array is dumped
entry-by-entry).
``type-value`` can have multiple levels of nesting, for example
genetlink's policy dumps create the following structures::
[POLICY-IDX]
[ATTR-IDX]
[POLICY-INFO-ATTR1]
[POLICY-INFO-ATTR2]
Where the first level of nest has the policy index as it's attribute
type, it contains a single nest which has the attribute index as its
type. Inside the attr-index nest are the policy attributes. Modern
Netlink families should have instead defined this as a flat structure,
the nesting serves no good purpose here.
Other quirks (todo)
===================
Structures
----------
Legacy families can define C structures both to be used as the contents
of an attribute and as a fixed message header. The plan is to define
the structs in ``definitions`` and link the appropriate attrs.
Multi-message DO
----------------
New Netlink families should never respond to a DO operation with multiple
replies, with ``NLM_F_MULTI`` set. Use a filtered dump instead.
At the spec level we can define a ``dumps`` property for the ``do``,
perhaps with values of ``combine`` and ``multi-object`` depending
on how the parsing should be implemented (parse into a single reply
vs list of objects i.e. pretty much a dump).
......@@ -10,3 +10,8 @@ Netlink documentation for users.
:maxdepth: 2
intro
specs
c-code-gen
genetlink-legacy
See also :ref:`Documentation/core-api/netlink.rst <kernel_netlink>`.
This diff is collapsed.
......@@ -14562,8 +14562,10 @@ Q: https://patchwork.kernel.org/project/netdevbpf/list/
B: mailto:netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
F: Documentation/core-api/netlink.rst
F: Documentation/networking/
F: Documentation/process/maintainer-netdev.rst
F: Documentation/userspace-api/netlink/
F: include/linux/in.h
F: include/linux/net.h
F: include/linux/netdevice.h
......@@ -14575,6 +14577,7 @@ F: include/uapi/linux/netdevice.h
F: lib/net_utils.c
F: lib/random32.c
F: net/
F: tools/net/
F: tools/testing/selftests/net/
NETWORKING [IPSEC]
......
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* fou.h - FOU Interface */
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/fou.yaml */
/* YNL-GEN uapi header */
#ifndef _UAPI_LINUX_FOU_H
#define _UAPI_LINUX_FOU_H
/* NETLINK_GENERIC related info
*/
#define FOU_GENL_NAME "fou"
#define FOU_GENL_VERSION 0x1
#define FOU_GENL_VERSION 1
enum {
FOU_ATTR_UNSPEC,
FOU_ATTR_PORT, /* u16 */
FOU_ATTR_AF, /* u8 */
FOU_ATTR_IPPROTO, /* u8 */
FOU_ATTR_TYPE, /* u8 */
FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */
FOU_ATTR_LOCAL_V4, /* u32 */
FOU_ATTR_LOCAL_V6, /* in6_addr */
FOU_ATTR_PEER_V4, /* u32 */
FOU_ATTR_PEER_V6, /* in6_addr */
FOU_ATTR_PEER_PORT, /* u16 */
FOU_ATTR_IFINDEX, /* s32 */
__FOU_ATTR_MAX,
FOU_ENCAP_UNSPEC,
FOU_ENCAP_DIRECT,
FOU_ENCAP_GUE,
};
#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1)
enum {
FOU_ATTR_UNSPEC,
FOU_ATTR_PORT,
FOU_ATTR_AF,
FOU_ATTR_IPPROTO,
FOU_ATTR_TYPE,
FOU_ATTR_REMCSUM_NOPARTIAL,
FOU_ATTR_LOCAL_V4,
FOU_ATTR_LOCAL_V6,
FOU_ATTR_PEER_V4,
FOU_ATTR_PEER_V6,
FOU_ATTR_PEER_PORT,
FOU_ATTR_IFINDEX,
__FOU_ATTR_MAX
};
#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1)
enum {
FOU_CMD_UNSPEC,
......@@ -34,15 +39,8 @@ enum {
FOU_CMD_DEL,
FOU_CMD_GET,
__FOU_CMD_MAX,
__FOU_CMD_MAX
};
enum {
FOU_ENCAP_UNSPEC,
FOU_ENCAP_DIRECT,
FOU_ENCAP_GUE,
};
#define FOU_CMD_MAX (__FOU_CMD_MAX - 1)
#define FOU_CMD_MAX (__FOU_CMD_MAX - 1)
#endif /* _UAPI_LINUX_FOU_H */
......@@ -26,6 +26,7 @@ obj-$(CONFIG_IP_MROUTE) += ipmr.o
obj-$(CONFIG_IP_MROUTE_COMMON) += ipmr_base.o
obj-$(CONFIG_NET_IPIP) += ipip.o
gre-y := gre_demux.o
fou-y := fou_core.o fou_nl.o
obj-$(CONFIG_NET_FOU) += fou.o
obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
obj-$(CONFIG_NET_IPGRE) += ip_gre.o
......
......@@ -19,6 +19,8 @@
#include <uapi/linux/fou.h>
#include <uapi/linux/genetlink.h>
#include "fou_nl.h"
struct fou {
struct socket *sock;
u8 protocol;
......@@ -640,20 +642,6 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg)
static struct genl_family fou_nl_family;
static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
[FOU_ATTR_PORT] = { .type = NLA_U16, },
[FOU_ATTR_AF] = { .type = NLA_U8, },
[FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
[FOU_ATTR_TYPE] = { .type = NLA_U8, },
[FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, },
[FOU_ATTR_LOCAL_V4] = { .type = NLA_U32, },
[FOU_ATTR_PEER_V4] = { .type = NLA_U32, },
[FOU_ATTR_LOCAL_V6] = { .len = sizeof(struct in6_addr), },
[FOU_ATTR_PEER_V6] = { .len = sizeof(struct in6_addr), },
[FOU_ATTR_PEER_PORT] = { .type = NLA_U16, },
[FOU_ATTR_IFINDEX] = { .type = NLA_S32, },
};
static int parse_nl_config(struct genl_info *info,
struct fou_cfg *cfg)
{
......@@ -745,7 +733,7 @@ static int parse_nl_config(struct genl_info *info,
return 0;
}
static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
int fou_nl_add_doit(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct fou_cfg cfg;
......@@ -758,7 +746,7 @@ static int fou_nl_cmd_add_port(struct sk_buff *skb, struct genl_info *info)
return fou_create(net, &cfg, NULL);
}
static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info)
int fou_nl_del_doit(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct fou_cfg cfg;
......@@ -827,7 +815,7 @@ static int fou_dump_info(struct fou *fou, u32 portid, u32 seq,
return -EMSGSIZE;
}
static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
int fou_nl_get_doit(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct fou_net *fn = net_generic(net, fou_net_id);
......@@ -874,7 +862,7 @@ static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
return ret;
}
static int fou_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
int fou_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct fou_net *fn = net_generic(net, fou_net_id);
......@@ -897,33 +885,12 @@ static int fou_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
static const struct genl_small_ops fou_nl_ops[] = {
{
.cmd = FOU_CMD_ADD,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = fou_nl_cmd_add_port,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = FOU_CMD_DEL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = fou_nl_cmd_rm_port,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = FOU_CMD_GET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = fou_nl_cmd_get_port,
.dumpit = fou_nl_dump,
},
};
static struct genl_family fou_nl_family __ro_after_init = {
.hdrsize = 0,
.name = FOU_GENL_NAME,
.version = FOU_GENL_VERSION,
.maxattr = FOU_ATTR_MAX,
.policy = fou_nl_policy,
.policy = fou_nl_policy,
.netnsok = true,
.module = THIS_MODULE,
.small_ops = fou_nl_ops,
......
// SPDX-License-Identifier: BSD-3-Clause
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/fou.yaml */
/* YNL-GEN kernel source */
#include <net/netlink.h>
#include <net/genetlink.h>
#include "fou_nl.h"
#include <linux/fou.h>
/* Global operation policy for fou */
const struct nla_policy fou_nl_policy[FOU_ATTR_IFINDEX + 1] = {
[FOU_ATTR_PORT] = { .type = NLA_U16, },
[FOU_ATTR_AF] = { .type = NLA_U8, },
[FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
[FOU_ATTR_TYPE] = { .type = NLA_U8, },
[FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, },
[FOU_ATTR_LOCAL_V4] = { .type = NLA_U32, },
[FOU_ATTR_LOCAL_V6] = { .len = 16, },
[FOU_ATTR_PEER_V4] = { .type = NLA_U32, },
[FOU_ATTR_PEER_V6] = { .len = 16, },
[FOU_ATTR_PEER_PORT] = { .type = NLA_U16, },
[FOU_ATTR_IFINDEX] = { .type = NLA_S32, },
};
/* Ops table for fou */
const struct genl_small_ops fou_nl_ops[3] = {
{
.cmd = FOU_CMD_ADD,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = fou_nl_add_doit,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = FOU_CMD_DEL,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = fou_nl_del_doit,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = FOU_CMD_GET,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = fou_nl_get_doit,
.dumpit = fou_nl_get_dumpit,
},
};
/* SPDX-License-Identifier: BSD-3-Clause */
/* Do not edit directly, auto-generated from: */
/* Documentation/netlink/specs/fou.yaml */
/* YNL-GEN kernel header */
#ifndef _LINUX_FOU_GEN_H
#define _LINUX_FOU_GEN_H
#include <net/netlink.h>
#include <net/genetlink.h>
#include <linux/fou.h>
/* Global operation policy for fou */
extern const struct nla_policy fou_nl_policy[FOU_ATTR_IFINDEX + 1];
/* Ops table for fou */
extern const struct genl_small_ops fou_nl_ops[3];
int fou_nl_add_doit(struct sk_buff *skb, struct genl_info *info);
int fou_nl_del_doit(struct sk_buff *skb, struct genl_info *info);
int fou_nl_get_doit(struct sk_buff *skb, struct genl_info *info);
int fou_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
#endif /* _LINUX_FOU_GEN_H */
#!/usr/bin/env python
# SPDX-License-Identifier: BSD-3-Clause
import argparse
import json
import pprint
import time
from ynl import YnlFamily
def main():
parser = argparse.ArgumentParser(description='YNL CLI sample')
parser.add_argument('--spec', dest='spec', type=str, required=True)
parser.add_argument('--schema', dest='schema', type=str)
parser.add_argument('--json', dest='json_text', type=str)
parser.add_argument('--do', dest='do', type=str)
parser.add_argument('--dump', dest='dump', type=str)
parser.add_argument('--sleep', dest='sleep', type=int)
parser.add_argument('--subscribe', dest='ntf', type=str)
args = parser.parse_args()
attrs = {}
if args.json_text:
attrs = json.loads(args.json_text)
ynl = YnlFamily(args.spec, args.schema)
if args.ntf:
ynl.ntf_subscribe(args.ntf)
if args.sleep:
time.sleep(args.sleep)
if args.do or args.dump:
method = getattr(ynl, args.do if args.do else args.dump)
reply = method(attrs, dump=bool(args.dump))
pprint.PrettyPrinter().pprint(reply)
if args.ntf:
ynl.check_ntf()
pprint.PrettyPrinter().pprint(ynl.async_msg_queue)
if __name__ == "__main__":
main()
This diff is collapsed.
This diff is collapsed.
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause
TOOL=$(dirname $(realpath $0))/ynl-gen-c.py
force=
while [ ! -z "$1" ]; do
case "$1" in
-f ) force=yes; shift ;;
* ) echo "Unrecognized option '$1'"; exit 1 ;;
esac
done
KDIR=$(dirname $(dirname $(dirname $(dirname $(realpath $0)))))
files=$(git grep --files-with-matches '^/\* YNL-GEN \(kernel\|uapi\)')
for f in $files; do
# params: 0 1 2 3
# $YAML YNL-GEN kernel $mode
params=( $(git grep -B1 -h '/\* YNL-GEN' $f | sed 's@/\*\(.*\)\*/@\1@') )
if [ $f -nt ${params[0]} -a -z "$force" ]; then
echo -e "\tSKIP $f"
continue
fi
echo -e "\tGEN ${params[2]}\t$f"
$TOOL --mode ${params[2]} --${params[3]} --spec $KDIR/${params[0]} -o $f
done
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment