zebra: move from NDA_NOTIFY to NDA_FDB_EXT_ATTRS

Use the new nested NDA_FDB_EXT_ATTRS attribute to control per-fdb
notifications.

PS: The attributes where updated as a part of the kernel upstreaming
hence the change.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
Nikolay Aleksandrov 2020-07-15 17:59:12 +03:00 committed by Anuradha Karuppiah
parent 9c47491551
commit 4bcdb6086c
5 changed files with 73 additions and 34 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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};
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;
netlink_parse_rtattr_nested(nfea_tb, NFEA_MAX, attr);
if (nfea_tb[NFEA_ACTIVITY_NOTIFY]) {
uint8_t nfy_flags;
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;
}