|
| 1 | +diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt |
| 2 | +index 7eb936642..e0faaa97b 100644 |
| 3 | +--- a/Documentation/networking/ip-sysctl.txt |
| 4 | ++++ b/Documentation/networking/ip-sysctl.txt |
| 5 | +@@ -1537,6 +1537,19 @@ accept_ra_defrtr - BOOLEAN |
| 6 | + Functional default: enabled if accept_ra is enabled. |
| 7 | + disabled if accept_ra is disabled. |
| 8 | + |
| 9 | ++ra_defrtr_metric - INTEGER |
| 10 | ++ Route metric for default route learned in Router Advertisement. This value |
| 11 | ++ will be assigned as metric for the default route learned via IPv6 Router |
| 12 | ++ Advertisement. Takes affect only if accept_ra_defrtr is enabled. |
| 13 | ++ |
| 14 | ++ Possible values are: |
| 15 | ++ 0: |
| 16 | ++ default value will be used for route metric |
| 17 | ++ i.e. IP6_RT_PRIO_USER 1024. |
| 18 | ++ 1 to 0xFFFFFFFF: |
| 19 | ++ current value will be used for route metric. |
| 20 | ++ |
| 21 | ++ |
| 22 | + accept_ra_from_local - BOOLEAN |
| 23 | + Accept RA with source-address that is found on local machine |
| 24 | + if the RA is otherwise proper and able to be accepted. |
| 25 | +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h |
| 26 | +index 8415bf1a9..ab98f5fa2 100644 |
| 27 | +--- a/include/linux/ipv6.h |
| 28 | ++++ b/include/linux/ipv6.h |
| 29 | +@@ -31,6 +31,7 @@ struct ipv6_devconf { |
| 30 | + __s32 max_desync_factor; |
| 31 | + __s32 max_addresses; |
| 32 | + __s32 accept_ra_defrtr; |
| 33 | ++ __u32 ra_defrtr_metric; |
| 34 | + __s32 accept_ra_min_hop_limit; |
| 35 | + __s32 accept_ra_pinfo; |
| 36 | + __s32 ignore_routes_with_linkdown; |
| 37 | +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h |
| 38 | +index 5e26d6186..7087fb5e5 100644 |
| 39 | +--- a/include/net/ip6_route.h |
| 40 | ++++ b/include/net/ip6_route.h |
| 41 | +@@ -153,7 +153,8 @@ struct fib6_info *rt6_get_dflt_router(struct net *net, |
| 42 | + struct net_device *dev); |
| 43 | + struct fib6_info *rt6_add_dflt_router(struct net *net, |
| 44 | + const struct in6_addr *gwaddr, |
| 45 | +- struct net_device *dev, unsigned int pref); |
| 46 | ++ struct net_device *dev, unsigned int pref, |
| 47 | ++ u32 defrtr_usr_metric); |
| 48 | + |
| 49 | + void rt6_purge_dflt_routers(struct net *net); |
| 50 | + |
| 51 | +diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h |
| 52 | +index 9c0f4a92b..481616cc2 100644 |
| 53 | +--- a/include/uapi/linux/ipv6.h |
| 54 | ++++ b/include/uapi/linux/ipv6.h |
| 55 | +@@ -187,6 +187,7 @@ enum { |
| 56 | + DEVCONF_DISABLE_POLICY, |
| 57 | + DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN, |
| 58 | + DEVCONF_NDISC_TCLASS, |
| 59 | ++ DEVCONF_RA_DEFRTR_METRIC, |
| 60 | + DEVCONF_MAX |
| 61 | + }; |
| 62 | + |
| 63 | +diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h |
| 64 | +index d71013fff..42fb25093 100644 |
| 65 | +--- a/include/uapi/linux/sysctl.h |
| 66 | ++++ b/include/uapi/linux/sysctl.h |
| 67 | +@@ -570,6 +570,7 @@ enum { |
| 68 | + NET_IPV6_ACCEPT_SOURCE_ROUTE=25, |
| 69 | + NET_IPV6_ACCEPT_RA_FROM_LOCAL=26, |
| 70 | + NET_IPV6_ACCEPT_RA_RT_INFO_MIN_PLEN=27, |
| 71 | ++ NET_IPV6_RA_DEFRTR_METRIC=28, |
| 72 | + __NET_IPV6_MAX |
| 73 | + }; |
| 74 | + |
| 75 | +diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c |
| 76 | +index 07148b497..67b5ef45b 100644 |
| 77 | +--- a/kernel/sysctl_binary.c |
| 78 | ++++ b/kernel/sysctl_binary.c |
| 79 | +@@ -525,6 +525,7 @@ static const struct bin_table bin_net_ipv6_conf_var_table[] = { |
| 80 | + { CTL_INT, NET_IPV6_PROXY_NDP, "proxy_ndp" }, |
| 81 | + { CTL_INT, NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" }, |
| 82 | + { CTL_INT, NET_IPV6_ACCEPT_RA_FROM_LOCAL, "accept_ra_from_local" }, |
| 83 | ++ { CTL_INT, NET_IPV6_RA_DEFRTR_METRIC, "ra_defrtr_metric" }, |
| 84 | + {} |
| 85 | + }; |
| 86 | + |
| 87 | +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c |
| 88 | +index 627cd24b7..2f68947c2 100644 |
| 89 | +--- a/net/ipv6/addrconf.c |
| 90 | ++++ b/net/ipv6/addrconf.c |
| 91 | +@@ -209,6 +209,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { |
| 92 | + .max_desync_factor = MAX_DESYNC_FACTOR, |
| 93 | + .max_addresses = IPV6_MAX_ADDRESSES, |
| 94 | + .accept_ra_defrtr = 1, |
| 95 | ++ .ra_defrtr_metric = 0, |
| 96 | + .accept_ra_from_local = 0, |
| 97 | + .accept_ra_min_hop_limit= 1, |
| 98 | + .accept_ra_pinfo = 1, |
| 99 | +@@ -263,6 +264,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { |
| 100 | + .max_desync_factor = MAX_DESYNC_FACTOR, |
| 101 | + .max_addresses = IPV6_MAX_ADDRESSES, |
| 102 | + .accept_ra_defrtr = 1, |
| 103 | ++ .ra_defrtr_metric = 0, |
| 104 | + .accept_ra_from_local = 0, |
| 105 | + .accept_ra_min_hop_limit= 1, |
| 106 | + .accept_ra_pinfo = 1, |
| 107 | +@@ -5199,6 +5201,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, |
| 108 | + array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; |
| 109 | + array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; |
| 110 | + array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; |
| 111 | ++ array[DEVCONF_RA_DEFRTR_METRIC] = cnf->ra_defrtr_metric; |
| 112 | + array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit; |
| 113 | + array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; |
| 114 | + #ifdef CONFIG_IPV6_ROUTER_PREF |
| 115 | +@@ -6347,6 +6350,13 @@ static const struct ctl_table addrconf_sysctl[] = { |
| 116 | + .mode = 0644, |
| 117 | + .proc_handler = proc_dointvec, |
| 118 | + }, |
| 119 | ++ { |
| 120 | ++ .procname = "ra_defrtr_metric", |
| 121 | ++ .data = &ipv6_devconf.ra_defrtr_metric, |
| 122 | ++ .maxlen = sizeof(u32), |
| 123 | ++ .mode = 0644, |
| 124 | ++ .proc_handler = proc_douintvec, |
| 125 | ++ }, |
| 126 | + { |
| 127 | + .procname = "accept_ra_min_hop_limit", |
| 128 | + .data = &ipv6_devconf.accept_ra_min_hop_limit, |
| 129 | +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c |
| 130 | +index 673a4a932..c350a16dd 100644 |
| 131 | +--- a/net/ipv6/ndisc.c |
| 132 | ++++ b/net/ipv6/ndisc.c |
| 133 | +@@ -1156,6 +1156,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) |
| 134 | + struct neighbour *neigh = NULL; |
| 135 | + struct inet6_dev *in6_dev; |
| 136 | + struct fib6_info *rt = NULL; |
| 137 | ++ u32 defrtr_usr_metric; |
| 138 | + struct net *net; |
| 139 | + int lifetime; |
| 140 | + struct ndisc_options ndopts; |
| 141 | +@@ -1287,18 +1288,23 @@ static void ndisc_router_discovery(struct sk_buff *skb) |
| 142 | + return; |
| 143 | + } |
| 144 | + } |
| 145 | +- if (rt && lifetime == 0) { |
| 146 | ++ /* Set default route metric if specified by user */ |
| 147 | ++ defrtr_usr_metric = in6_dev->cnf.ra_defrtr_metric; |
| 148 | ++ if (defrtr_usr_metric == 0) |
| 149 | ++ defrtr_usr_metric = IP6_RT_PRIO_USER; |
| 150 | ++ /* delete the route if lifetime is 0 or if metric needs change */ |
| 151 | ++ if (rt && ((lifetime == 0) || (rt->fib6_metric != defrtr_usr_metric))) { |
| 152 | + ip6_del_rt(net, rt); |
| 153 | + rt = NULL; |
| 154 | + } |
| 155 | + |
| 156 | +- ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, for dev: %s\n", |
| 157 | +- rt, lifetime, skb->dev->name); |
| 158 | ++ ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, metric: %d, for dev: %s\n", |
| 159 | ++ rt, lifetime, defrtr_usr_metric, skb->dev->name); |
| 160 | + if (!rt && lifetime) { |
| 161 | + ND_PRINTK(3, info, "RA: adding default router\n"); |
| 162 | + |
| 163 | + rt = rt6_add_dflt_router(net, &ipv6_hdr(skb)->saddr, |
| 164 | +- skb->dev, pref); |
| 165 | ++ skb->dev, pref, defrtr_usr_metric); |
| 166 | + if (!rt) { |
| 167 | + ND_PRINTK(0, err, |
| 168 | + "RA: %s failed to add default route\n", |
| 169 | +diff --git a/net/ipv6/route.c b/net/ipv6/route.c |
| 170 | +index 9c36a743d..8b3fddc50 100644 |
| 171 | +--- a/net/ipv6/route.c |
| 172 | ++++ b/net/ipv6/route.c |
| 173 | +@@ -3608,11 +3608,12 @@ struct fib6_info *rt6_get_dflt_router(struct net *net, |
| 174 | + struct fib6_info *rt6_add_dflt_router(struct net *net, |
| 175 | + const struct in6_addr *gwaddr, |
| 176 | + struct net_device *dev, |
| 177 | +- unsigned int pref) |
| 178 | ++ unsigned int pref, |
| 179 | ++ u32 defrtr_usr_metric) |
| 180 | + { |
| 181 | + struct fib6_config cfg = { |
| 182 | + .fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT, |
| 183 | +- .fc_metric = IP6_RT_PRIO_USER, |
| 184 | ++ .fc_metric = defrtr_usr_metric ? : IP6_RT_PRIO_USER, |
| 185 | + .fc_ifindex = dev->ifindex, |
| 186 | + .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | |
| 187 | + RTF_UP | RTF_EXPIRES | RTF_PREF(pref), |
0 commit comments