ipv6: export function to send route updates
Add fib6_rt_update to send RTM_NEWROUTE with NLM_F_REPLACE set. This helper will be used by the nexthop code to notify userspace of routes that are impacted when a nexthop config is updated via replace. This notification is needed for legacy apps that do not understand the new nexthop object. Apps that are nexthop aware can use the RTA_NH_ID attribute in the route notification to just ignore it. In the future this should be wrapped in a sysctl to allow OS'es that are fully updated to avoid the notificaton storm. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cdaa16a4f7
commit
19a3b7eea4
|
@ -452,6 +452,12 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
|
||||||
struct netlink_ext_ack *extack);
|
struct netlink_ext_ack *extack);
|
||||||
void fib6_nh_release(struct fib6_nh *fib6_nh);
|
void fib6_nh_release(struct fib6_nh *fib6_nh);
|
||||||
|
|
||||||
|
int call_fib6_entry_notifiers(struct net *net,
|
||||||
|
enum fib_event_type event_type,
|
||||||
|
struct fib6_info *rt,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
void fib6_rt_update(struct net *net, struct fib6_info *rt,
|
||||||
|
struct nl_info *info);
|
||||||
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
|
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,9 @@ struct ipv6_stub {
|
||||||
void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
|
void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
|
||||||
void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt);
|
void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt);
|
||||||
int (*ip6_del_rt)(struct net *net, struct fib6_info *rt);
|
int (*ip6_del_rt)(struct net *net, struct fib6_info *rt);
|
||||||
|
void (*fib6_rt_update)(struct net *net, struct fib6_info *rt,
|
||||||
|
struct nl_info *info);
|
||||||
|
|
||||||
void (*udpv6_encap_enable)(void);
|
void (*udpv6_encap_enable)(void);
|
||||||
void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
|
void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
|
||||||
const struct in6_addr *solicited_addr,
|
const struct in6_addr *solicited_addr,
|
||||||
|
|
|
@ -927,6 +927,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
|
||||||
.fib6_nh_init = fib6_nh_init,
|
.fib6_nh_init = fib6_nh_init,
|
||||||
.fib6_nh_release = fib6_nh_release,
|
.fib6_nh_release = fib6_nh_release,
|
||||||
.fib6_update_sernum = fib6_update_sernum_stub,
|
.fib6_update_sernum = fib6_update_sernum_stub,
|
||||||
|
.fib6_rt_update = fib6_rt_update,
|
||||||
.ip6_del_rt = ip6_del_rt,
|
.ip6_del_rt = ip6_del_rt,
|
||||||
.udpv6_encap_enable = udpv6_encap_enable,
|
.udpv6_encap_enable = udpv6_encap_enable,
|
||||||
.ndisc_send_na = ndisc_send_na,
|
.ndisc_send_na = ndisc_send_na,
|
||||||
|
|
|
@ -393,10 +393,10 @@ static int call_fib6_entry_notifier(struct notifier_block *nb, struct net *net,
|
||||||
return call_fib6_notifier(nb, net, event_type, &info.info);
|
return call_fib6_notifier(nb, net, event_type, &info.info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int call_fib6_entry_notifiers(struct net *net,
|
int call_fib6_entry_notifiers(struct net *net,
|
||||||
enum fib_event_type event_type,
|
enum fib_event_type event_type,
|
||||||
struct fib6_info *rt,
|
struct fib6_info *rt,
|
||||||
struct netlink_ext_ack *extack)
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct fib6_entry_notifier_info info = {
|
struct fib6_entry_notifier_info info = {
|
||||||
.info.extack = extack,
|
.info.extack = extack,
|
||||||
|
|
|
@ -5123,6 +5123,38 @@ errout:
|
||||||
rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
|
rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fib6_rt_update(struct net *net, struct fib6_info *rt,
|
||||||
|
struct nl_info *info)
|
||||||
|
{
|
||||||
|
u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
int err = -ENOBUFS;
|
||||||
|
|
||||||
|
/* call_fib6_entry_notifiers will be removed when in-kernel notifier
|
||||||
|
* is implemented and supported for nexthop objects
|
||||||
|
*/
|
||||||
|
call_fib6_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE, rt, NULL);
|
||||||
|
|
||||||
|
skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
|
||||||
|
if (!skb)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
err = rt6_fill_node(net, skb, rt, NULL, NULL, NULL, 0,
|
||||||
|
RTM_NEWROUTE, info->portid, seq, NLM_F_REPLACE);
|
||||||
|
if (err < 0) {
|
||||||
|
/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
|
||||||
|
WARN_ON(err == -EMSGSIZE);
|
||||||
|
kfree_skb(skb);
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
|
||||||
|
info->nlh, gfp_any());
|
||||||
|
return;
|
||||||
|
errout:
|
||||||
|
if (err < 0)
|
||||||
|
rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
|
||||||
|
}
|
||||||
|
|
||||||
static int ip6_route_dev_notify(struct notifier_block *this,
|
static int ip6_route_dev_notify(struct notifier_block *this,
|
||||||
unsigned long event, void *ptr)
|
unsigned long event, void *ptr)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue