diff options
author | Tom Gundersen <teg@jklm.no> | 2015-02-08 12:37:05 +0100 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2015-02-08 17:43:39 +0100 |
commit | 4af7b60d428765c2d2c66c46f416f6dae55e9ddb (patch) | |
tree | ed1f20a91b4c4c5a87d73fbba4eb2f9c875ec65c /src/libsystemd/sd-rtnl/rtnl-types.c | |
parent | 02f500532e4823584aae43cbe762914b4a0c0254 (diff) |
sd-rtnl: extend type system to allow address-family to decide the union members
So far we only supported selecting them by sibling attributes.
(This stuff is all a bit crazy, but there seems to be no other way...)
Diffstat (limited to 'src/libsystemd/sd-rtnl/rtnl-types.c')
-rw-r--r-- | src/libsystemd/sd-rtnl/rtnl-types.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c index d4abe4cc3b..4ef698a7f5 100644 --- a/src/libsystemd/sd-rtnl/rtnl-types.c +++ b/src/libsystemd/sd-rtnl/rtnl-types.c @@ -224,6 +224,7 @@ static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { .num = _NL_UNION_LINK_INFO_DATA_MAX, .lookup = nl_union_link_info_data_from_string, .type_systems = rtnl_link_info_data_type_systems, + .match_type = NL_MATCH_SIBLING, .match = IFLA_INFO_KIND, }; @@ -242,7 +243,7 @@ static const NLTypeSystem rtnl_link_info_type_system = { .types = rtnl_link_info_types, }; -static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = { +static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = { [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, [IFLA_BRPORT_COST] = { .type = NLA_U32 }, [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, @@ -253,9 +254,15 @@ static const struct NLType rtnl_bridge_port_types[IFLA_BRPORT_MAX + 1] = { [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, }; -static const NLTypeSystem rtnl_bridge_port_type_system = { - .max = ELEMENTSOF(rtnl_bridge_port_types) - 1, - .types = rtnl_bridge_port_types, +static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = { + [AF_BRIDGE] = { .max = ELEMENTSOF(rtnl_prot_info_bridge_port_types) - 1, + .types = rtnl_prot_info_bridge_port_types }, +}; + +static const NLTypeSystemUnion rtnl_prot_info_type_system_union = { + .num = AF_MAX, + .type_systems = rtnl_prot_info_type_systems, + .match_type = NL_MATCH_PROTOCOL, }; static const NLType rtnl_link_types[IFLA_MAX + 1 ] = { @@ -273,9 +280,8 @@ static const NLType rtnl_link_types[IFLA_MAX + 1 ] = { [IFLA_MASTER] = { .type = NLA_U32 }, /* [IFLA_WIRELESS], - [IFLA_PROTINFO], */ - [IFLA_PROTINFO] = { .type = NLA_NESTED, .type_system = &rtnl_bridge_port_type_system }, + [IFLA_PROTINFO] = { .type = NLA_UNION, .type_system_union = &rtnl_prot_info_type_system_union }, [IFLA_TXQLEN] = { .type = NLA_U32 }, /* [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, @@ -463,6 +469,7 @@ int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union int type; assert(type_system_union); + assert_return(type_system_union->match_type == NL_MATCH_SIBLING, -EINVAL); assert(type_system_union->lookup); assert(type_system_union->type_systems); assert(ret); @@ -478,3 +485,25 @@ int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union return 0; } + +int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) { + const NLTypeSystem *type_system; + + assert(type_system_union); + assert(type_system_union->type_systems); + assert(ret); + assert_return(type_system_union->match_type == NL_MATCH_PROTOCOL, -EINVAL); + assert_return(protocol < type_system_union->num, -EINVAL); + + if (protocol >= type_system_union->num) + return -ENOTSUP; + + type_system = &type_system_union->type_systems[protocol]; + + if (!type_system) + return -ENOTSUP; + + *ret = type_system; + + return 0; +} |