summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_bridge.h11
-rw-r--r--include/linux/neighbour.h25
-rw-r--r--zebra/kernel_netlink.c13
-rw-r--r--zebra/kernel_netlink.h3
-rw-r--r--zebra/rt_netlink.c55
5 files changed, 73 insertions, 34 deletions
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 50011d55e..fb79481cb 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -293,15 +293,4 @@ struct br_mcast_stats {
__u64 mcast_bytes[BR_MCAST_DIR_SIZE];
__u64 mcast_packets[BR_MCAST_DIR_SIZE];
};
-
-/* FDB notification bits for NDA_NOTIFY:
- * - BR_FDB_NFY_STATIC - notify on activity/expire even for a static entry
- * - BR_FDB_NFY_INACTIVE - mark as inactive to avoid double notification,
- * used with BR_FDB_NFY_STATIC (kernel controlled)
- */
-enum {
- BR_FDB_NFY_STATIC,
- BR_FDB_NFY_INACTIVE,
- BR_FDB_NFY_MAX
-};
#endif /* _UAPI_LINUX_IF_BRIDGE_H */
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index c06fe708f..581af73c7 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -30,7 +30,7 @@ enum {
NDA_SRC_VNI,
NDA_PROTOCOL, /* Originator of entry */
NDA_NH_ID,
- NDA_NOTIFY,
+ NDA_FDB_EXT_ATTRS,
NDA_EXT_FLAGS,
__NDA_MAX
};
@@ -178,4 +178,27 @@ enum {
};
#define NDTA_MAX (__NDTA_MAX - 1)
+/* FDB activity notification bits used in NFEA_ACTIVITY_NOTIFY:
+ * - FDB_NOTIFY_BIT - notify on activity/expire for any entry
+ * - FDB_NOTIFY_INACTIVE_BIT - mark as inactive to avoid multiple notifications
+ */
+enum {
+ FDB_NOTIFY_BIT = (1 << 0),
+ FDB_NOTIFY_INACTIVE_BIT = (1 << 1)
+};
+
+/* embedded into NDA_FDB_EXT_ATTRS:
+ * [NDA_FDB_EXT_ATTRS] = {
+ * [NFEA_ACTIVITY_NOTIFY]
+ * ...
+ * }
+ */
+enum {
+ NFEA_UNSPEC,
+ NFEA_ACTIVITY_NOTIFY,
+ NFEA_DONT_REFRESH,
+ __NFEA_MAX
+};
+#define NFEA_MAX (__NFEA_MAX - 1)
+
#endif
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 76da00c61..59c0d252d 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -489,6 +489,19 @@ static void netlink_install_filter(int sock, __u32 pid, __u32 dplane_pid)
safe_strerror(errno));
}
+void netlink_parse_rtattr_flags(struct rtattr **tb, int max,
+ struct rtattr *rta, int len, unsigned short flags)
+{
+ unsigned short type;
+
+ while (RTA_OK(rta, len)) {
+ type = rta->rta_type & ~flags;
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+}
+
void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
int len)
{
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 696f9be4f..a7b152b31 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -79,6 +79,9 @@ extern void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh);
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
struct rtattr *rta, int len);
+extern void netlink_parse_rtattr_flags(struct rtattr **tb, int max,
+ struct rtattr *rta, int len,
+ unsigned short flags);
extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
struct rtattr *rta);
extern const char *nl_msg_type_to_str(uint16_t msg_type);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f59fbae3a..d16fa3615 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -77,16 +77,7 @@
/* Re-defining as I am unable to include <linux/if_bridge.h> which has the
* UAPI for MAC sync. */
#ifndef _UAPI_LINUX_IF_BRIDGE_H
-/* FDB notification bits for NDA_NOTIFY:
- * - BR_FDB_NFY_STATIC - notify on activity/expire even for a static entry
- * - BR_FDB_NFY_INACTIVE - mark as inactive to avoid double notification,
- * used with BR_FDB_NFY_STATIC (kernel controlled)
- */
-enum {
- BR_FDB_NFY_STATIC,
- BR_FDB_NFY_INACTIVE,
- BR_FDB_NFY_MAX
-};
+#define BR_SPH_LIST_SIZE 10
#endif
static vlanid_t filter_vlan = 0;
@@ -2762,11 +2753,23 @@ static ssize_t netlink_neigh_update_msg_encode(
}
if (nfy) {
- if (!nl_attr_put(&req->n, datalen, NDA_NOTIFY,
- &nfy_flags, sizeof(nfy_flags)))
+ struct rtattr *nest;
+
+ nest = nl_attr_nest(&req->n, datalen,
+ NDA_FDB_EXT_ATTRS | NLA_F_NESTED);
+ if (!nest)
+ return 0;
+
+ if (!nl_attr_put(&req->n, datalen, NFEA_ACTIVITY_NOTIFY,
+ &nfy_flags, sizeof(nfy_flags)))
return 0;
+ if (!nl_attr_put(&req->n, datalen, NFEA_DONT_REFRESH, NULL, 0))
+ return 0;
+
+ nl_attr_nest_end(&req->n, nest);
}
+
if (ext) {
if (!nl_attr_put(&req->n, datalen, NDA_EXT_FLAGS, &ext_flags,
sizeof(ext_flags)))
@@ -2851,7 +2854,8 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* validation of the fields.
*/
memset(tb, 0, sizeof tb);
- netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
+ netlink_parse_rtattr_flags(tb, NDA_MAX, NDA_RTA(ndm), len,
+ NLA_F_NESTED);
if (!tb[NDA_LLADDR]) {
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -2893,14 +2897,21 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (ndm->ndm_state & NUD_STALE)
local_inactive = true;
- if (tb[NDA_NOTIFY]) {
- uint8_t nfy_flags;
+ if (tb[NDA_FDB_EXT_ATTRS]) {
+ struct rtattr *attr = tb[NDA_FDB_EXT_ATTRS];
+ struct rtattr *nfea_tb[NFEA_MAX + 1] = {0};
+
+ netlink_parse_rtattr_nested(nfea_tb, NFEA_MAX, attr);
+ if (nfea_tb[NFEA_ACTIVITY_NOTIFY]) {
+ uint8_t nfy_flags;
- dp_static = true;
- nfy_flags = *(uint8_t *)RTA_DATA(tb[NDA_NOTIFY]);
- /* local activity has not been detected on the entry */
- if (nfy_flags & (1 << BR_FDB_NFY_INACTIVE))
- local_inactive = true;
+ nfy_flags = *(uint8_t *)RTA_DATA(
+ nfea_tb[NFEA_ACTIVITY_NOTIFY]);
+ if (nfy_flags & FDB_NOTIFY_BIT)
+ dp_static = true;
+ if (nfy_flags & FDB_NOTIFY_INACTIVE_BIT)
+ local_inactive = true;
+ }
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -3202,12 +3213,12 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
} else {
/* local mac */
if (update_flags & DPLANE_MAC_SET_STATIC) {
- nfy_flags |= (1 << BR_FDB_NFY_STATIC);
+ nfy_flags |= FDB_NOTIFY_BIT;
state |= NUD_NOARP;
}
if (update_flags & DPLANE_MAC_SET_INACTIVE)
- nfy_flags |= (1 << BR_FDB_NFY_INACTIVE);
+ nfy_flags |= FDB_NOTIFY_INACTIVE_BIT;
nfy = true;
}