Linux IPv6 Device Start
IPV6地址格式
IPv6地址由被划分为8个16位块的128位组成。 然后将每个块转换为由冒号符号分隔的4位十六进制数字。
2001:0000:3238:00E1:0063:0000:0000:FEFB
每一块多个前导的0可以省略,一个块全为0可以简写为一个0,,多个块为连续0的话可以简写为:: 但是多个块的省略只能使用一次。
2001:0:3238:E1:0063::FEFB
URL中ipv6如要使用地址必须加[]
http://[2001:0:3238:E1:0063::FEFB]:80

详细可见 <RFC 2460>
地址结构:
struct in6_addr {
union {
__u8 u6_addr8[16];
#if __UAPI_DEF_IN6_ADDR_ALT
__be16 u6_addr16[8];
__be32 u6_addr32[4];
#endif
} in6_u;
IPv6 地址的生成方式
Link-Local Address

除手动配置外,一般在某一 interface enable ipv6 时,该 interface 会根据响应,会在内核中生成一个 fe80 开头的本地链路地址。具体代码位置如下:
/*
* linux-3.4.11\net\ipv6\addrconf.c
*/
int __init addrconf_init(void)
{
...
register_netdevice_notifier(&ipv6_dev_notf);
...
}
static struct notifier_block ipv6_dev_notf = {
.notifier_call = addrconf_notify,
};
static int addrconf_notify(struct notifier_block *this, unsigned long event,
void * data)
{
struct net_device *dev = (struct net_device *) data;
struct inet6_dev *idev = __in6_dev_get(dev);
int run_pending = 0;
int err;
switch (event) {
....
case NETDEV_UP:
case NETDEV_CHANGE:
....
default:
addrconf_dev_config(dev);
....
}
static void addrconf_dev_config(struct net_device *dev)
{
struct in6_addr addr;
struct inet6_dev * idev;
ASSERT_RTNL();
if ((dev->type != ARPHRD_ETHER) &&
(dev->type != ARPHRD_FDDI) &&
(dev->type != ARPHRD_IEEE802_TR) &&
(dev->type != ARPHRD_ARCNET) &&
(dev->type != ARPHRD_INFINIBAND)) {
/* Alas, we support only Ethernet autoconfiguration. */
return;
}
idev = addrconf_add_dev(dev);
if (IS_ERR(idev))
return;
memset(&addr, 0, sizeof(struct in6_addr));
addr.s6_addr32[0] = htonl(0xFE800000);
if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0)
addrconf_add_linklocal(idev, &addr);
}
Send RS
If the device starts, it will be send RS data packet.
Still in “addrconf_notify” function.
static void addrconf_dad_run(struct inet6_dev *idev)
{
struct inet6_ifaddr *ifp;
read_lock_bh(&idev->lock);
list_for_each_entry(ifp, &idev->addr_list, if_list) {
spin_lock(&ifp->lock);
if (ifp->flags & IFA_F_TENTATIVE &&
ifp->state == INET6_IFADDR_STATE_DAD)
addrconf_dad_kick(ifp);
spin_unlock(&ifp->lock);
}
read_unlock_bh(&idev->lock);
}
static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
{
unsigned long rand_num;
struct inet6_dev *idev = ifp->idev;
if (ifp->flags & IFA_F_OPTIMISTIC)
rand_num = 0;
else
rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
ifp->probes = idev->cnf.dad_transmits;
addrconf_mod_timer(ifp, AC_DAD, rand_num);
}
addrconf_mod_timer -> addrconf_dad_timer -> ndisc_send_ns
Therefore, If you reset the interface and the interface will send the RS packet.
TODO
- How to send RS packet
- What other things the device dose.

