|
| 1 | +Allow user to set ipv6 Router Advertisement(RA) metric. |
| 2 | + |
| 3 | +Linux kernel allows user configured metric on IPv4 default |
| 4 | +routes learned via DHCP. For IPv6, default router is added |
| 5 | +via RA message, where currently a fixed metric value 1024 |
| 6 | +is applied. We should allow user to set ipv6 RA metric. |
| 7 | + |
| 8 | +Fix: |
| 9 | +Add new field in ipv6_devconf for RA default route metric. |
| 10 | + i.e accept_ra_defrtr_metric. |
| 11 | +Add accept_ra_defrtr_metric as sysctl. |
| 12 | +If accept_ra_defrtr_metric is set, then change metric on |
| 13 | + default route, whenever new IPv6 RA is received. |
| 14 | + |
| 15 | +Note: Metric is changed on default route only when new IPv6 |
| 16 | + RA is received. |
| 17 | + |
| 18 | +Signed-off-by: Praveen Chaudhary < [email protected]> |
| 19 | +Signed-off-by: Zhenggen Xu < [email protected]> |
| 20 | +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h |
| 21 | +index b9dfca5..9b70be7 100644 |
| 22 | +--- a/include/linux/ipv6.h |
| 23 | ++++ b/include/linux/ipv6.h |
| 24 | +@@ -30,6 +30,7 @@ struct ipv6_devconf { |
| 25 | + __s32 max_desync_factor; |
| 26 | + __s32 max_addresses; |
| 27 | + __s32 accept_ra_defrtr; |
| 28 | ++ __u32 accept_ra_defrtr_metric; |
| 29 | + __s32 accept_ra_min_hop_limit; |
| 30 | + __s32 accept_ra_pinfo; |
| 31 | + __s32 ignore_routes_with_linkdown; |
| 32 | +diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h |
| 33 | +index 8c27723..36d7097 100644 |
| 34 | +--- a/include/uapi/linux/ipv6.h |
| 35 | ++++ b/include/uapi/linux/ipv6.h |
| 36 | +@@ -152,6 +152,7 @@ enum { |
| 37 | + DEVCONF_MAX_ADDRESSES, |
| 38 | + DEVCONF_FORCE_MLD_VERSION, |
| 39 | + DEVCONF_ACCEPT_RA_DEFRTR, |
| 40 | ++ DEVCONF_ACCEPT_RA_DEFRTR_METRIC, |
| 41 | + DEVCONF_ACCEPT_RA_PINFO, |
| 42 | + DEVCONF_ACCEPT_RA_RTR_PREF, |
| 43 | + DEVCONF_RTR_PROBE_INTERVAL, |
| 44 | +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c |
| 45 | +index 4ce7f91..529db12 100644 |
| 46 | +--- a/net/ipv6/addrconf.c |
| 47 | ++++ b/net/ipv6/addrconf.c |
| 48 | +@@ -216,6 +216,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { |
| 49 | + .max_desync_factor = MAX_DESYNC_FACTOR, |
| 50 | + .max_addresses = IPV6_MAX_ADDRESSES, |
| 51 | + .accept_ra_defrtr = 1, |
| 52 | ++ .accept_ra_defrtr_metric = 0, |
| 53 | + .accept_ra_from_local = 0, |
| 54 | + .accept_ra_min_hop_limit= 1, |
| 55 | + .accept_ra_pinfo = 1, |
| 56 | +@@ -262,6 +263,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { |
| 57 | + .max_desync_factor = MAX_DESYNC_FACTOR, |
| 58 | + .max_addresses = IPV6_MAX_ADDRESSES, |
| 59 | + .accept_ra_defrtr = 1, |
| 60 | ++ .accept_ra_defrtr_metric = 0, |
| 61 | + .accept_ra_from_local = 0, |
| 62 | + .accept_ra_min_hop_limit= 1, |
| 63 | + .accept_ra_pinfo = 1, |
| 64 | +@@ -4951,6 +4953,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, |
| 65 | + array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor; |
| 66 | + array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses; |
| 67 | + array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr; |
| 68 | ++ array[DEVCONF_ACCEPT_RA_DEFRTR_METRIC] = cnf->accept_ra_defrtr_metric; |
| 69 | + array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit; |
| 70 | + array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo; |
| 71 | + #ifdef CONFIG_IPV6_ROUTER_PREF |
| 72 | +@@ -5903,6 +5906,13 @@ static const struct ctl_table addrconf_sysctl[] = { |
| 73 | + .proc_handler = proc_dointvec, |
| 74 | + }, |
| 75 | + { |
| 76 | ++ .procname = "accept_ra_defrtr_metric", |
| 77 | ++ .data = &ipv6_devconf.accept_ra_defrtr_metric, |
| 78 | ++ .maxlen = sizeof(u32), |
| 79 | ++ .mode = 0644, |
| 80 | ++ .proc_handler = proc_douintvec, |
| 81 | ++ }, |
| 82 | ++ { |
| 83 | + .procname = "accept_ra_min_hop_limit", |
| 84 | + .data = &ipv6_devconf.accept_ra_min_hop_limit, |
| 85 | + .maxlen = sizeof(int), |
| 86 | +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c |
| 87 | +index 505d048..eb6f16f 100644 |
| 88 | +--- a/net/ipv6/ndisc.c |
| 89 | ++++ b/net/ipv6/ndisc.c |
| 90 | +@@ -1279,8 +1279,12 @@ static void ndisc_router_discovery(struct sk_buff *skb) |
| 91 | + rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); |
| 92 | + } |
| 93 | + |
| 94 | +- if (rt) |
| 95 | ++ if (rt) { |
| 96 | + rt6_set_expires(rt, jiffies + (HZ * lifetime)); |
| 97 | ++ /* Set metric as per ipv6 dev cnf */ |
| 98 | ++ if (in6_dev->cnf.accept_ra_defrtr_metric) |
| 99 | ++ rt->rt6i_metric = in6_dev->cnf.accept_ra_defrtr_metric; |
| 100 | ++ } |
| 101 | + if (in6_dev->cnf.accept_ra_min_hop_limit < 256 && |
| 102 | + ra_msg->icmph.icmp6_hop_limit) { |
| 103 | + if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) { |
0 commit comments