Commit dbcefdeb authored by Matt Johnston's avatar Matt Johnston Committed by Jakub Kicinski

mctp: emit RTM_NEWADDR and RTM_DELADDR

Userspace can receive notification of MCTP address changes via
RTNLGRP_MCTP_IFADDR rtnetlink multicast group.
Signed-off-by: default avatarMatt Johnston <matt@codeconstruct.com.au>
Link: https://lore.kernel.org/r/20211220023104.1965509-1-matt@codeconstruct.com.auSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 4b430f5c
...@@ -754,6 +754,8 @@ enum rtnetlink_groups { ...@@ -754,6 +754,8 @@ enum rtnetlink_groups {
#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP #define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
RTNLGRP_BRVLAN, RTNLGRP_BRVLAN,
#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN #define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
RTNLGRP_MCTP_IFADDR,
#define RTNLGRP_MCTP_IFADDR RTNLGRP_MCTP_IFADDR
__RTNLGRP_MAX __RTNLGRP_MAX
}; };
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1) #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
......
...@@ -35,14 +35,24 @@ struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev) ...@@ -35,14 +35,24 @@ struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev)
return rtnl_dereference(dev->mctp_ptr); return rtnl_dereference(dev->mctp_ptr);
} }
static int mctp_fill_addrinfo(struct sk_buff *skb, struct netlink_callback *cb, static int mctp_addrinfo_size(void)
struct mctp_dev *mdev, mctp_eid_t eid) {
return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+ nla_total_size(1) // IFA_LOCAL
+ nla_total_size(1) // IFA_ADDRESS
;
}
/* flag should be NLM_F_MULTI for dump calls */
static int mctp_fill_addrinfo(struct sk_buff *skb,
struct mctp_dev *mdev, mctp_eid_t eid,
int msg_type, u32 portid, u32 seq, int flag)
{ {
struct ifaddrmsg *hdr; struct ifaddrmsg *hdr;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, nlh = nlmsg_put(skb, portid, seq,
RTM_NEWADDR, sizeof(*hdr), NLM_F_MULTI); msg_type, sizeof(*hdr), flag);
if (!nlh) if (!nlh)
return -EMSGSIZE; return -EMSGSIZE;
...@@ -72,10 +82,14 @@ static int mctp_dump_dev_addrinfo(struct mctp_dev *mdev, struct sk_buff *skb, ...@@ -72,10 +82,14 @@ static int mctp_dump_dev_addrinfo(struct mctp_dev *mdev, struct sk_buff *skb,
struct netlink_callback *cb) struct netlink_callback *cb)
{ {
struct mctp_dump_cb *mcb = (void *)cb->ctx; struct mctp_dump_cb *mcb = (void *)cb->ctx;
u32 portid, seq;
int rc = 0; int rc = 0;
portid = NETLINK_CB(cb->skb).portid;
seq = cb->nlh->nlmsg_seq;
for (; mcb->a_idx < mdev->num_addrs; mcb->a_idx++) { for (; mcb->a_idx < mdev->num_addrs; mcb->a_idx++) {
rc = mctp_fill_addrinfo(skb, cb, mdev, mdev->addrs[mcb->a_idx]); rc = mctp_fill_addrinfo(skb, mdev, mdev->addrs[mcb->a_idx],
RTM_NEWADDR, portid, seq, NLM_F_MULTI);
if (rc < 0) if (rc < 0)
break; break;
} }
...@@ -127,6 +141,32 @@ static int mctp_dump_addrinfo(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -127,6 +141,32 @@ static int mctp_dump_addrinfo(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len; return skb->len;
} }
static void mctp_addr_notify(struct mctp_dev *mdev, mctp_eid_t eid, int msg_type,
struct sk_buff *req_skb, struct nlmsghdr *req_nlh)
{
u32 portid = NETLINK_CB(req_skb).portid;
struct net *net = dev_net(mdev->dev);
struct sk_buff *skb;
int rc = -ENOBUFS;
skb = nlmsg_new(mctp_addrinfo_size(), GFP_KERNEL);
if (!skb)
goto out;
rc = mctp_fill_addrinfo(skb, mdev, eid, msg_type,
portid, req_nlh->nlmsg_seq, 0);
if (rc < 0) {
WARN_ON_ONCE(rc == -EMSGSIZE);
goto out;
}
rtnl_notify(skb, net, portid, RTNLGRP_MCTP_IFADDR, req_nlh, GFP_KERNEL);
return;
out:
kfree_skb(skb);
rtnl_set_sk_err(net, RTNLGRP_MCTP_IFADDR, rc);
}
static const struct nla_policy ifa_mctp_policy[IFA_MAX + 1] = { static const struct nla_policy ifa_mctp_policy[IFA_MAX + 1] = {
[IFA_ADDRESS] = { .type = NLA_U8 }, [IFA_ADDRESS] = { .type = NLA_U8 },
[IFA_LOCAL] = { .type = NLA_U8 }, [IFA_LOCAL] = { .type = NLA_U8 },
...@@ -189,6 +229,7 @@ static int mctp_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -189,6 +229,7 @@ static int mctp_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
kfree(tmp_addrs); kfree(tmp_addrs);
mctp_addr_notify(mdev, addr->s_addr, RTM_NEWADDR, skb, nlh);
mctp_route_add_local(mdev, addr->s_addr); mctp_route_add_local(mdev, addr->s_addr);
return 0; return 0;
...@@ -244,6 +285,8 @@ static int mctp_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -244,6 +285,8 @@ static int mctp_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
mdev->num_addrs--; mdev->num_addrs--;
spin_unlock_irqrestore(&mdev->addrs_lock, flags); spin_unlock_irqrestore(&mdev->addrs_lock, flags);
mctp_addr_notify(mdev, addr->s_addr, RTM_DELADDR, skb, nlh);
return 0; return 0;
} }
......
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