@@ -76,6 +76,7 @@ struct ipv6_devconf {
__s32 disable_policy;
__s32 ndisc_tclass;
__s32 rpl_seg_enabled;
+ __s32 disable_gen_linklocal_addr;
struct ctl_table_header *sysctl_header;
};
@@ -190,6 +190,7 @@ enum {
DEVCONF_NDISC_TCLASS,
DEVCONF_RPL_SEG_ENABLED,
DEVCONF_RA_DEFRTR_METRIC,
+ DEVCONF_DISABLE_GEN_LINKLOCAL_ADDR,
DEVCONF_MAX
};
@@ -237,6 +237,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
.disable_policy = 0,
.rpl_seg_enabled = 0,
+ .disable_gen_linklocal_addr = 0,
};
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -293,6 +294,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64,
.disable_policy = 0,
.rpl_seg_enabled = 0,
+ .disable_gen_linklocal_addr = 0,
};
/* Check if link is ready: is it up and is a valid qdisc available */
@@ -3352,6 +3354,12 @@ static void addrconf_dev_config(struct net_device *dev)
if (IS_ERR(idev))
return;
+ if (idev->cnf.disable_gen_linklocal_addr) {
+ pr_info("%s: IPv6 link-local address being disabled\n",
+ idev->dev->name);
+ return;
+ }
+
/* this device type has no EUI support */
if (dev->type == ARPHRD_NONE &&
idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)
@@ -5526,6 +5534,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy;
array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass;
array[DEVCONF_RPL_SEG_ENABLED] = cnf->rpl_seg_enabled;
+ array[DEVCONF_DISABLE_GEN_LINKLOCAL_ADDR] = cnf->disable_gen_linklocal_addr;
}
static inline size_t inet6_ifla6_size(void)
@@ -6932,6 +6941,13 @@ static const struct ctl_table addrconf_sysctl[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "disable_gen_linklocal_addr",
+ .data = &ipv6_devconf.disable_gen_linklocal_addr,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
{
/* sentinel */
}
This patch provides an ipv6 proc file named "disable_gen_linklocal_addr", its absolute path is as follows: "/proc/sys/net/ipv6/conf/<iface>/disable_gen_linklocal_addr". When the "disable_gen_linklocal_addr" value of a device is 1, it means that this device does not need the Linux kernel to automatically generate the ipv6 link-local address no matter which IN6_ADDR_GEN_MODE is used. The reasons why the kernel does not need to automatically generate the ipv6 link-local address are as follows: (1) In the 3GPP TS 29.061, here is a description as follows: "in order to avoid any conflict between the link-local address of the MS and that of the GGSN, the Interface-Identifier used by the MS to build its link-local address shall be assigned by the GGSN. The GGSN ensures the uniqueness of this Interface- Identifier. The MT shall then enforce the use of this Interface-Identifier by the TE" In other words, in the cellular network, GGSN determines whether to reply a solicited RA message by identifying the low 64 bits of the source address of the received RS message. Therefore, cellular network device's ipv6 link-local address should be set as the format of fe80::(GGSN assigned IID). For example: When using a new kernel and ARPHRD_RAWIP, kernel will generate an EUI64 format ipv6 link-local address, and the Linux kernel will uses this link-local address to send RS message. The result is that the GGSN will not reply to the RS message with a solicited RA message. Although the combination of IN6_ADDR_GEN_MODE_NONE + ARPHRD_NONE can avoid the above problem (1), when the addr_gen_mode is changed to the IN6_ADDR_GEN_MODE_STABLE_PRIVACY, the above problem still exist. The detail as follows: (2) Among global mobile operators, some operators have already request MT (Mobile Terminal) to support RFC7217, such as AT&T. This means that the device not only needs the IID assigned by the GGSN to build the ipv6 link-local address to trigger the RS message, but also needs to use the stable privacy mode to build the ipv6 global address after receiving the RA. Obviously using APRHRD_NONE and IN6_ADDR_GEN_MODE_STABLE_PRIVACY mode cannot achieve this. In summary, using the "disable_gen_linklocal_addr" proc file can disable kernel auto generate ipv6 link-local address no matter which addr_gen_mode is used. Signed-off-by: Rocco Yue <rocco.yue@mediatek.com> --- include/linux/ipv6.h | 1 + include/uapi/linux/ipv6.h | 1 + net/ipv6/addrconf.c | 16 ++++++++++++++++ 3 files changed, 18 insertions(+)