mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
ipmr: add netlink notifications on igmpmsg cache reports
Add Netlink notifications on cache reports in ipmr, in addition to the existing igmpmsg sent to mroute_sk. Send RTM_NEWCACHEREPORT notifications to RTNLGRP_IPV4_MROUTE_R. MSGTYPE, VIF_ID, SRC_ADDR and DST_ADDR Netlink attributes contain the same data as their equivalent fields in the igmpmsg header. PKT attribute is the packet sent to mroute_sk, without the added igmpmsg header. Suggested-by: Ryan Halbrook <halbrook@arista.com> Signed-off-by: Julien Gomes <julien@arista.com> Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5f729eaabe
commit
5a645dd86c
@ -152,6 +152,18 @@ enum {
|
|||||||
};
|
};
|
||||||
#define IPMRA_VIFA_MAX (__IPMRA_VIFA_MAX - 1)
|
#define IPMRA_VIFA_MAX (__IPMRA_VIFA_MAX - 1)
|
||||||
|
|
||||||
|
/* ipmr netlink cache report attributes */
|
||||||
|
enum {
|
||||||
|
IPMRA_CREPORT_UNSPEC,
|
||||||
|
IPMRA_CREPORT_MSGTYPE,
|
||||||
|
IPMRA_CREPORT_VIF_ID,
|
||||||
|
IPMRA_CREPORT_SRC_ADDR,
|
||||||
|
IPMRA_CREPORT_DST_ADDR,
|
||||||
|
IPMRA_CREPORT_PKT,
|
||||||
|
__IPMRA_CREPORT_MAX
|
||||||
|
};
|
||||||
|
#define IPMRA_CREPORT_MAX (__IPMRA_CREPORT_MAX - 1)
|
||||||
|
|
||||||
/* That's all usermode folks */
|
/* That's all usermode folks */
|
||||||
|
|
||||||
#define MFC_ASSERT_THRESH (3*HZ) /* Maximal freq. of asserts */
|
#define MFC_ASSERT_THRESH (3*HZ) /* Maximal freq. of asserts */
|
||||||
|
@ -109,6 +109,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
|
|||||||
struct mfc_cache *c, struct rtmsg *rtm);
|
struct mfc_cache *c, struct rtmsg *rtm);
|
||||||
static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
|
static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
|
||||||
int cmd);
|
int cmd);
|
||||||
|
static void igmpmsg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
|
||||||
static void mroute_clean_tables(struct mr_table *mrt, bool all);
|
static void mroute_clean_tables(struct mr_table *mrt, bool all);
|
||||||
static void ipmr_expire_process(unsigned long arg);
|
static void ipmr_expire_process(unsigned long arg);
|
||||||
|
|
||||||
@ -995,8 +996,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bounce a cache query up to mrouted. We could use netlink for this but mrouted
|
/* Bounce a cache query up to mrouted and netlink.
|
||||||
* expects the following bizarre scheme.
|
|
||||||
*
|
*
|
||||||
* Called under mrt_lock.
|
* Called under mrt_lock.
|
||||||
*/
|
*/
|
||||||
@ -1062,6 +1062,8 @@ static int ipmr_cache_report(struct mr_table *mrt,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
igmpmsg_netlink_event(mrt, skb);
|
||||||
|
|
||||||
/* Deliver to mrouted */
|
/* Deliver to mrouted */
|
||||||
ret = sock_queue_rcv_skb(mroute_sk, skb);
|
ret = sock_queue_rcv_skb(mroute_sk, skb);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -2341,6 +2343,69 @@ errout:
|
|||||||
rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE, err);
|
rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t igmpmsg_netlink_msgsize(size_t payloadlen)
|
||||||
|
{
|
||||||
|
size_t len =
|
||||||
|
NLMSG_ALIGN(sizeof(struct rtgenmsg))
|
||||||
|
+ nla_total_size(1) /* IPMRA_CREPORT_MSGTYPE */
|
||||||
|
+ nla_total_size(4) /* IPMRA_CREPORT_VIF_ID */
|
||||||
|
+ nla_total_size(4) /* IPMRA_CREPORT_SRC_ADDR */
|
||||||
|
+ nla_total_size(4) /* IPMRA_CREPORT_DST_ADDR */
|
||||||
|
/* IPMRA_CREPORT_PKT */
|
||||||
|
+ nla_total_size(payloadlen)
|
||||||
|
;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void igmpmsg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
|
||||||
|
{
|
||||||
|
struct net *net = read_pnet(&mrt->net);
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtgenmsg *rtgenm;
|
||||||
|
struct igmpmsg *msg;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct nlattr *nla;
|
||||||
|
int payloadlen;
|
||||||
|
|
||||||
|
payloadlen = pkt->len - sizeof(struct igmpmsg);
|
||||||
|
msg = (struct igmpmsg *)skb_network_header(pkt);
|
||||||
|
|
||||||
|
skb = nlmsg_new(igmpmsg_netlink_msgsize(payloadlen), GFP_ATOMIC);
|
||||||
|
if (!skb)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
|
||||||
|
sizeof(struct rtgenmsg), 0);
|
||||||
|
if (!nlh)
|
||||||
|
goto errout;
|
||||||
|
rtgenm = nlmsg_data(nlh);
|
||||||
|
rtgenm->rtgen_family = RTNL_FAMILY_IPMR;
|
||||||
|
if (nla_put_u8(skb, IPMRA_CREPORT_MSGTYPE, msg->im_msgtype) ||
|
||||||
|
nla_put_u32(skb, IPMRA_CREPORT_VIF_ID, msg->im_vif) ||
|
||||||
|
nla_put_in_addr(skb, IPMRA_CREPORT_SRC_ADDR,
|
||||||
|
msg->im_src.s_addr) ||
|
||||||
|
nla_put_in_addr(skb, IPMRA_CREPORT_DST_ADDR,
|
||||||
|
msg->im_dst.s_addr))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
nla = nla_reserve(skb, IPMRA_CREPORT_PKT, payloadlen);
|
||||||
|
if (!nla || skb_copy_bits(pkt, sizeof(struct igmpmsg),
|
||||||
|
nla_data(nla), payloadlen))
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
|
nlmsg_end(skb, nlh);
|
||||||
|
|
||||||
|
rtnl_notify(skb, net, 0, RTNLGRP_IPV4_MROUTE_R, NULL, GFP_ATOMIC);
|
||||||
|
return;
|
||||||
|
|
||||||
|
nla_put_failure:
|
||||||
|
nlmsg_cancel(skb, nlh);
|
||||||
|
errout:
|
||||||
|
kfree_skb(skb);
|
||||||
|
rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE_R, -ENOBUFS);
|
||||||
|
}
|
||||||
|
|
||||||
static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
|
static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
|
||||||
{
|
{
|
||||||
struct net *net = sock_net(skb->sk);
|
struct net *net = sock_net(skb->sk);
|
||||||
|
Loading…
Reference in New Issue
Block a user