ipv4: teach ipconfig about the MTU option in DHCP
The DHCP spec allows the server to specify the MTU. This can be useful for netbooting with UDP-based NFS-root on a network using jumbo frames. This patch allows the kernel IP autoconfiguration to handle this option correctly. It would be possible to use initramfs and add a script to set the MTU, but that seems like a complicated solution if no initramfs is otherwise necessary, and would bloat the kernel image more than this code would. This patch was originally submitted to LKML in 2003 by Hans-Peter Jansen. Signed-off-by: Chris Friesen <cfriesen@nortel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fd2120ca0d
commit
9643f45512
|
@ -160,6 +160,9 @@ static char user_dev_name[IFNAMSIZ] __initdata = { 0, };
|
||||||
/* Protocols supported by available interfaces */
|
/* Protocols supported by available interfaces */
|
||||||
static int ic_proto_have_if __initdata = 0;
|
static int ic_proto_have_if __initdata = 0;
|
||||||
|
|
||||||
|
/* MTU for boot device */
|
||||||
|
static int ic_dev_mtu __initdata = 0;
|
||||||
|
|
||||||
#ifdef IPCONFIG_DYNAMIC
|
#ifdef IPCONFIG_DYNAMIC
|
||||||
static DEFINE_SPINLOCK(ic_recv_lock);
|
static DEFINE_SPINLOCK(ic_recv_lock);
|
||||||
static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */
|
static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */
|
||||||
|
@ -286,7 +289,7 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
|
||||||
sin->sin_port = port;
|
sin->sin_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
|
static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
@ -297,6 +300,17 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
mm_segment_t oldfs = get_fs();
|
||||||
|
set_fs(get_ds());
|
||||||
|
res = dev_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
|
||||||
|
set_fs(oldfs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
|
static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
@ -321,20 +335,31 @@ static int __init ic_setup_if(void)
|
||||||
memset(&ir, 0, sizeof(ir));
|
memset(&ir, 0, sizeof(ir));
|
||||||
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
|
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
|
||||||
set_sockaddr(sin, ic_myaddr, 0);
|
set_sockaddr(sin, ic_myaddr, 0);
|
||||||
if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) {
|
if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) {
|
||||||
printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
|
printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
set_sockaddr(sin, ic_netmask, 0);
|
set_sockaddr(sin, ic_netmask, 0);
|
||||||
if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
|
if ((err = ic_devinet_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
|
||||||
printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
|
printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
|
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
|
||||||
if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
|
if ((err = ic_devinet_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
|
||||||
printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
|
printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* Handle the case where we need non-standard MTU on the boot link (a network
|
||||||
|
* using jumbo frames, for instance). If we can't set the mtu, don't error
|
||||||
|
* out, we'll try to muddle along.
|
||||||
|
*/
|
||||||
|
if (ic_dev_mtu != 0) {
|
||||||
|
strcpy(ir.ifr_name, ic_dev->name);
|
||||||
|
ir.ifr_mtu = ic_dev_mtu;
|
||||||
|
if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0)
|
||||||
|
printk(KERN_ERR "IP-Config: Unable to set interface mtu to %d (%d).\n",
|
||||||
|
ic_dev_mtu, err);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +648,7 @@ ic_dhcp_init_options(u8 *options)
|
||||||
12, /* Host name */
|
12, /* Host name */
|
||||||
15, /* Domain name */
|
15, /* Domain name */
|
||||||
17, /* Boot path */
|
17, /* Boot path */
|
||||||
|
26, /* MTU */
|
||||||
40, /* NIS domain name */
|
40, /* NIS domain name */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -798,6 +824,7 @@ static void __init ic_do_bootp_ext(u8 *ext)
|
||||||
{
|
{
|
||||||
u8 servers;
|
u8 servers;
|
||||||
int i;
|
int i;
|
||||||
|
u16 mtu;
|
||||||
|
|
||||||
#ifdef IPCONFIG_DEBUG
|
#ifdef IPCONFIG_DEBUG
|
||||||
u8 *c;
|
u8 *c;
|
||||||
|
@ -837,6 +864,10 @@ static void __init ic_do_bootp_ext(u8 *ext)
|
||||||
if (!root_server_path[0])
|
if (!root_server_path[0])
|
||||||
ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
|
ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
|
||||||
break;
|
break;
|
||||||
|
case 26: /* Interface MTU */
|
||||||
|
memcpy(&mtu, ext+1, sizeof(mtu));
|
||||||
|
ic_dev_mtu = ntohs(mtu);
|
||||||
|
break;
|
||||||
case 40: /* NIS Domain name (_not_ DNS) */
|
case 40: /* NIS Domain name (_not_ DNS) */
|
||||||
ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN);
|
ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN);
|
||||||
break;
|
break;
|
||||||
|
@ -1403,6 +1434,8 @@ static int __init ip_auto_config(void)
|
||||||
printk(",\n bootserver=%pI4", &ic_servaddr);
|
printk(",\n bootserver=%pI4", &ic_servaddr);
|
||||||
printk(", rootserver=%pI4", &root_server_addr);
|
printk(", rootserver=%pI4", &root_server_addr);
|
||||||
printk(", rootpath=%s", root_server_path);
|
printk(", rootpath=%s", root_server_path);
|
||||||
|
if (ic_dev_mtu)
|
||||||
|
printk(", mtu=%d", ic_dev_mtu);
|
||||||
printk("\n");
|
printk("\n");
|
||||||
#endif /* !SILENT */
|
#endif /* !SILENT */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue