aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorChris Friesen <cfriesen@nortel.com>2009-05-19 18:31:50 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-19 18:36:17 -0400
commit9643f4551255ce8b3ef7470aaaf7f435a20f9182 (patch)
tree4c2fe5194a697c2e9c0e61d7a74850760315ba76 /net/ipv4
parentfd2120ca0da9108e53f8db2fe57ab74fca76fd56 (diff)
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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ipconfig.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 88bf051d0cbb..f8d04c256454 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -160,6 +160,9 @@ static char user_dev_name[IFNAMSIZ] __initdata = { 0, };
160/* Protocols supported by available interfaces */ 160/* Protocols supported by available interfaces */
161static int ic_proto_have_if __initdata = 0; 161static int ic_proto_have_if __initdata = 0;
162 162
163/* MTU for boot device */
164static int ic_dev_mtu __initdata = 0;
165
163#ifdef IPCONFIG_DYNAMIC 166#ifdef IPCONFIG_DYNAMIC
164static DEFINE_SPINLOCK(ic_recv_lock); 167static DEFINE_SPINLOCK(ic_recv_lock);
165static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */ 168static 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)
286 sin->sin_port = port; 289 sin->sin_port = port;
287} 290}
288 291
289static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg) 292static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg)
290{ 293{
291 int res; 294 int res;
292 295
@@ -297,6 +300,17 @@ static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
297 return res; 300 return res;
298} 301}
299 302
303static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
304{
305 int res;
306
307 mm_segment_t oldfs = get_fs();
308 set_fs(get_ds());
309 res = dev_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
310 set_fs(oldfs);
311 return res;
312}
313
300static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg) 314static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
301{ 315{
302 int res; 316 int res;
@@ -321,20 +335,31 @@ static int __init ic_setup_if(void)
321 memset(&ir, 0, sizeof(ir)); 335 memset(&ir, 0, sizeof(ir));
322 strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); 336 strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
323 set_sockaddr(sin, ic_myaddr, 0); 337 set_sockaddr(sin, ic_myaddr, 0);
324 if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) { 338 if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) {
325 printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err); 339 printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
326 return -1; 340 return -1;
327 } 341 }
328 set_sockaddr(sin, ic_netmask, 0); 342 set_sockaddr(sin, ic_netmask, 0);
329 if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) { 343 if ((err = ic_devinet_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
330 printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err); 344 printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
331 return -1; 345 return -1;
332 } 346 }
333 set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); 347 set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
334 if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { 348 if ((err = ic_devinet_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
335 printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err); 349 printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
336 return -1; 350 return -1;
337 } 351 }
352 /* Handle the case where we need non-standard MTU on the boot link (a network
353 * using jumbo frames, for instance). If we can't set the mtu, don't error
354 * out, we'll try to muddle along.
355 */
356 if (ic_dev_mtu != 0) {
357 strcpy(ir.ifr_name, ic_dev->name);
358 ir.ifr_mtu = ic_dev_mtu;
359 if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0)
360 printk(KERN_ERR "IP-Config: Unable to set interface mtu to %d (%d).\n",
361 ic_dev_mtu, err);
362 }
338 return 0; 363 return 0;
339} 364}
340 365
@@ -623,6 +648,7 @@ ic_dhcp_init_options(u8 *options)
623 12, /* Host name */ 648 12, /* Host name */
624 15, /* Domain name */ 649 15, /* Domain name */
625 17, /* Boot path */ 650 17, /* Boot path */
651 26, /* MTU */
626 40, /* NIS domain name */ 652 40, /* NIS domain name */
627 }; 653 };
628 654
@@ -798,6 +824,7 @@ static void __init ic_do_bootp_ext(u8 *ext)
798{ 824{
799 u8 servers; 825 u8 servers;
800 int i; 826 int i;
827 u16 mtu;
801 828
802#ifdef IPCONFIG_DEBUG 829#ifdef IPCONFIG_DEBUG
803 u8 *c; 830 u8 *c;
@@ -837,6 +864,10 @@ static void __init ic_do_bootp_ext(u8 *ext)
837 if (!root_server_path[0]) 864 if (!root_server_path[0])
838 ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path)); 865 ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
839 break; 866 break;
867 case 26: /* Interface MTU */
868 memcpy(&mtu, ext+1, sizeof(mtu));
869 ic_dev_mtu = ntohs(mtu);
870 break;
840 case 40: /* NIS Domain name (_not_ DNS) */ 871 case 40: /* NIS Domain name (_not_ DNS) */
841 ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN); 872 ic_bootp_string(utsname()->domainname, ext+1, *ext, __NEW_UTS_LEN);
842 break; 873 break;
@@ -1403,6 +1434,8 @@ static int __init ip_auto_config(void)
1403 printk(",\n bootserver=%pI4", &ic_servaddr); 1434 printk(",\n bootserver=%pI4", &ic_servaddr);
1404 printk(", rootserver=%pI4", &root_server_addr); 1435 printk(", rootserver=%pI4", &root_server_addr);
1405 printk(", rootpath=%s", root_server_path); 1436 printk(", rootpath=%s", root_server_path);
1437 if (ic_dev_mtu)
1438 printk(", mtu=%d", ic_dev_mtu);
1406 printk("\n"); 1439 printk("\n");
1407#endif /* !SILENT */ 1440#endif /* !SILENT */
1408 1441