summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRonan Dalton <ronan.dalton@alliedtelesis.co.nz>2024-09-12 22:46:54 (GMT)
committerRonan Dalton <ronan.dalton@alliedtelesis.co.nz>2024-09-16 23:32:16 (GMT)
commit3b284a118daf7989cfc53eee6c20a960019b3a1e (patch)
tree02e7179430b21a06d15287385c8c2ce60b52b3ae /lib
parenta43a41cd2b1128a1b0b428b98cc251bff2c24b2f (diff)
downloadlibnl-3b284a118daf7989cfc53eee6c20a960019b3a1e.zip
libnl-3b284a118daf7989cfc53eee6c20a960019b3a1e.tar.gz
libnl-3b284a118daf7989cfc53eee6c20a960019b3a1e.tar.bz2
lib/route: extend bridge info support
Add support for the following attributes for bridge links: IFLA_BR_STP_STATE IFLA_BR_MCAST_ROUTER IFLA_BR_MCAST_SNOOPING
Diffstat (limited to 'lib')
-rw-r--r--lib/route/link/bridge_info.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c
index 7250b43..0e4fdea 100644
--- a/lib/route/link/bridge_info.c
+++ b/lib/route/link/bridge_info.c
@@ -26,6 +26,9 @@
#define BRIDGE_ATTR_NF_CALL_IPTABLES (1 << 5)
#define BRIDGE_ATTR_NF_CALL_IP6TABLES (1 << 6)
#define BRIDGE_ATTR_NF_CALL_ARPTABLES (1 << 7)
+#define BRIDGE_ATTR_STP_STATE (1 << 8)
+#define BRIDGE_ATTR_MCAST_ROUTER (1 << 9)
+#define BRIDGE_ATTR_MCAST_SNOOPING (1 << 10)
struct bridge_info {
uint32_t ce_mask; /* to support attr macros */
@@ -37,6 +40,9 @@ struct bridge_info {
uint8_t b_nf_call_iptables;
uint8_t b_nf_call_ip6tables;
uint8_t b_nf_call_arptables;
+ uint32_t b_stp_state;
+ uint8_t b_mcast_router;
+ uint8_t b_mcast_snooping;
};
static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
@@ -48,6 +54,9 @@ static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
[IFLA_BR_NF_CALL_IPTABLES] = { .type = NLA_U8 },
[IFLA_BR_NF_CALL_IP6TABLES] = { .type = NLA_U8 },
[IFLA_BR_NF_CALL_ARPTABLES] = { .type = NLA_U8 },
+ [IFLA_BR_STP_STATE] = { .type = NLA_U32 },
+ [IFLA_BR_MCAST_ROUTER] = { .type = NLA_U8 },
+ [IFLA_BR_MCAST_SNOOPING] = { .type = NLA_U8 },
};
static inline struct bridge_info *bridge_info(struct rtnl_link *link)
@@ -136,6 +145,21 @@ static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data,
bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
}
+ if (tb[IFLA_BR_STP_STATE]) {
+ bi->b_stp_state = nla_get_u32(tb[IFLA_BR_STP_STATE]);
+ bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
+ }
+
+ if (tb[IFLA_BR_MCAST_ROUTER]) {
+ bi->b_mcast_router = nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]);
+ bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
+ }
+
+ if (tb[IFLA_BR_MCAST_SNOOPING]) {
+ bi->b_mcast_snooping = nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]);
+ bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
+ }
+
return 0;
}
@@ -178,6 +202,15 @@ static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
NLA_PUT_U8(msg, IFLA_BR_NF_CALL_ARPTABLES,
bi->b_nf_call_arptables);
+ if (bi->ce_mask & BRIDGE_ATTR_STP_STATE)
+ NLA_PUT_U32(msg, IFLA_BR_STP_STATE, bi->b_stp_state);
+
+ if (bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER)
+ NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, bi->b_mcast_router);
+
+ if (bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING)
+ NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, bi->b_mcast_snooping);
+
nla_nest_end(msg, data);
return 0;
@@ -605,6 +638,147 @@ int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link,
return 0;
}
+/**
+ * Set STP state
+ * @arg link Link object of type bridge
+ * @arg stp_state STP state to set. Typically 0 or 1.
+ *
+ * @see rtnl_link_bridge_get_stp_state()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, uint32_t stp_state)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ bi->b_stp_state = stp_state;
+
+ bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
+}
+
+/**
+ * Get STP state
+ * @arg link Link object of type bridge
+ * @arg stp_state Output argument.
+ *
+ * @see rtnl_link_bridge_set_stp_state()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, uint32_t *stp_state)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ if (!(bi->ce_mask & BRIDGE_ATTR_STP_STATE))
+ return -NLE_NOATTR;
+
+ if (!stp_state)
+ return -NLE_INVAL;
+
+ *stp_state = bi->b_stp_state;
+ return 0;
+}
+
+/**
+ * Set multicast router type
+ * @arg link Link object of type bridge
+ * @arg type Multicast router type (MDB_RTR_TYPE_*)
+ *
+ * @see rtnl_link_bridge_get_mcast_router()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, uint8_t type)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ bi->b_mcast_router = type;
+
+ bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
+}
+
+/**
+ * Get multicast router type
+ * @arg link Link object of type bridge
+ * @arg type Output argument.
+ *
+ * @see rtnl_link_bridge_set_mcast_router()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, uint8_t *type)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER))
+ return -NLE_NOATTR;
+
+ if (!type)
+ return -NLE_INVAL;
+
+ *type = bi->b_mcast_router;
+ return 0;
+}
+
+/**
+ * Set multicast snooping
+ * @arg link Link object of type bridge
+ * @arg value Value to set. Typically 0 or 1.
+ *
+ * @see rtnl_link_bridge_get_mcast_snooping()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, uint8_t value)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ bi->b_mcast_snooping = value;
+
+ bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
+}
+
+/**
+ * Get multicast snooping value
+ * @arg link Link object of type bridge
+ * @arg value Output argument.
+ *
+ * @see rtnl_link_bridge_set_mcast_snooping()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING))
+ return -NLE_NOATTR;
+
+ if (!value)
+ return -NLE_INVAL;
+
+ *value = bi->b_mcast_snooping;
+ return 0;
+}
+
static void _nl_init bridge_info_init(void)
{
rtnl_link_register_info(&bridge_info_ops);