summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2019-05-22 15:04:41 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-22 20:48:43 -0400
commit19a3b7eea42402accf52bcb9ddb51bfdb4d7a13b (patch)
treea7829e17b8cc38db2e463e4ab6eacc3318a6ff39
parentcdaa16a4f70cfa6c55641588c3a3eb9b53abd56b (diff)
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>
-rw-r--r--include/net/ip6_fib.h6
-rw-r--r--include/net/ipv6_stubs.h3
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/ip6_fib.c8
-rw-r--r--net/ipv6/route.c32
5 files changed, 46 insertions, 4 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index d038d02cbc3c..0d0d06b1cd26 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -452,6 +452,12 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
452 struct netlink_ext_ack *extack); 452 struct netlink_ext_ack *extack);
453void fib6_nh_release(struct fib6_nh *fib6_nh); 453void fib6_nh_release(struct fib6_nh *fib6_nh);
454 454
455int call_fib6_entry_notifiers(struct net *net,
456 enum fib_event_type event_type,
457 struct fib6_info *rt,
458 struct netlink_ext_ack *extack);
459void fib6_rt_update(struct net *net, struct fib6_info *rt,
460 struct nl_info *info);
455void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, 461void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
456 unsigned int flags); 462 unsigned int flags);
457 463
diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
index 97f42e16b3b3..5c93e942c50b 100644
--- a/include/net/ipv6_stubs.h
+++ b/include/net/ipv6_stubs.h
@@ -47,6 +47,9 @@ struct ipv6_stub {
47 void (*fib6_nh_release)(struct fib6_nh *fib6_nh); 47 void (*fib6_nh_release)(struct fib6_nh *fib6_nh);
48 void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt); 48 void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt);
49 int (*ip6_del_rt)(struct net *net, struct fib6_info *rt); 49 int (*ip6_del_rt)(struct net *net, struct fib6_info *rt);
50 void (*fib6_rt_update)(struct net *net, struct fib6_info *rt,
51 struct nl_info *info);
52
50 void (*udpv6_encap_enable)(void); 53 void (*udpv6_encap_enable)(void);
51 void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr, 54 void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
52 const struct in6_addr *solicited_addr, 55 const struct in6_addr *solicited_addr,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 55138f0d2b9d..cc6f8d0c625a 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -927,6 +927,7 @@ static const struct ipv6_stub ipv6_stub_impl = {
927 .fib6_nh_init = fib6_nh_init, 927 .fib6_nh_init = fib6_nh_init,
928 .fib6_nh_release = fib6_nh_release, 928 .fib6_nh_release = fib6_nh_release,
929 .fib6_update_sernum = fib6_update_sernum_stub, 929 .fib6_update_sernum = fib6_update_sernum_stub,
930 .fib6_rt_update = fib6_rt_update,
930 .ip6_del_rt = ip6_del_rt, 931 .ip6_del_rt = ip6_del_rt,
931 .udpv6_encap_enable = udpv6_encap_enable, 932 .udpv6_encap_enable = udpv6_encap_enable,
932 .ndisc_send_na = ndisc_send_na, 933 .ndisc_send_na = ndisc_send_na,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index df726fb8f70f..7958cf91895a 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -393,10 +393,10 @@ static int call_fib6_entry_notifier(struct notifier_block *nb, struct net *net,
393 return call_fib6_notifier(nb, net, event_type, &info.info); 393 return call_fib6_notifier(nb, net, event_type, &info.info);
394} 394}
395 395
396static int call_fib6_entry_notifiers(struct net *net, 396int call_fib6_entry_notifiers(struct net *net,
397 enum fib_event_type event_type, 397 enum fib_event_type event_type,
398 struct fib6_info *rt, 398 struct fib6_info *rt,
399 struct netlink_ext_ack *extack) 399 struct netlink_ext_ack *extack)
400{ 400{
401 struct fib6_entry_notifier_info info = { 401 struct fib6_entry_notifier_info info = {
402 .info.extack = extack, 402 .info.extack = extack,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7a014ca877ed..c52a7f49d096 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -5123,6 +5123,38 @@ errout:
5123 rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); 5123 rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
5124} 5124}
5125 5125
5126void fib6_rt_update(struct net *net, struct fib6_info *rt,
5127 struct nl_info *info)
5128{
5129 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
5130 struct sk_buff *skb;
5131 int err = -ENOBUFS;
5132
5133 /* call_fib6_entry_notifiers will be removed when in-kernel notifier
5134 * is implemented and supported for nexthop objects
5135 */
5136 call_fib6_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE, rt, NULL);
5137
5138 skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any());
5139 if (!skb)
5140 goto errout;
5141
5142 err = rt6_fill_node(net, skb, rt, NULL, NULL, NULL, 0,
5143 RTM_NEWROUTE, info->portid, seq, NLM_F_REPLACE);
5144 if (err < 0) {
5145 /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
5146 WARN_ON(err == -EMSGSIZE);
5147 kfree_skb(skb);
5148 goto errout;
5149 }
5150 rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
5151 info->nlh, gfp_any());
5152 return;
5153errout:
5154 if (err < 0)
5155 rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
5156}
5157
5126static int ip6_route_dev_notify(struct notifier_block *this, 5158static int ip6_route_dev_notify(struct notifier_block *this,
5127 unsigned long event, void *ptr) 5159 unsigned long event, void *ptr)
5128{ 5160{