Skip to contentSkip to conversation

ipconfig dhcp mtu option support

PATCH New Hans-Peter Jansen 1 participant 1 message Jun 22, 2003

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ipconfig dhcp mtu option support

Hi,

while experimenting with jumbo frames in a diskless setup, I came across the problem to enable them properly on the client. This is due to missing support for the dhcp interface-mtu option in ipconfig.

It took me this patch to make them work. Note, that I ommited the bootp_init_ext, so this one is limited to dhcp by now... While at it, I've cleaned up the ifreq struct usage a bit.

If you're going to test this, please let me know, if it __works__ for you, too, since I plan to send it to Marcelo, when 'enough' positives arrived here.

BTW, anybody willing to apply and test this on 2.5?

Enjoy,
Pete

P.S.: I'm using e1000 (Intel Pro/1000 MT Desktop) GB NICs here.

net/ipv4/ipconfig.c renamed from net/ipv4/ipconfig.c.orig +37 -6
@@ -27,10 +27,13 @@
  *  Merged changes from 2.2.19 into 2.4.3
  *              -- Eric Biederman <[email protected]>, 22 April Aug 2001
  *
  *  Multipe Nameservers in /proc/net/pnp
  *              --  Josef Siemes <[email protected]>, Aug 2002
+ *
+ *  Support for MTU selection via DHCP
+ *              -- Hans-Peter Jansen <[email protected]>, June 2003
  */
 
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -144,10 +147,13 @@
  */
 
 /* Name of user-selected boot device */
 static char user_dev_name[IFNAMSIZ] __initdata = { 0, };
 
+/* MTU of device (if requested) */
+static int ic_dev_mtu __initdata = 0;
+
 /* Protocols supported by available interfaces */
 static int ic_proto_have_if __initdata = 0;
 
 #ifdef IPCONFIG_DYNAMIC
 static spinlock_t ic_recv_lock = SPIN_LOCK_UNLOCKED;
@@ -262,21 +268,32 @@
 	sin->sin_family = AF_INET;
 	sin->sin_addr.s_addr = addr;
 	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;
 
 	mm_segment_t oldfs = get_fs();
 	set_fs(get_ds());
 	res = devinet_ioctl(cmd, arg);
 	set_fs(oldfs);
 	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(cmd, arg);
+	set_fs(oldfs);
+	return res;
+}
+
 static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
 {
 	int res;
 
 	mm_segment_t oldfs = get_fs();
@@ -291,30 +308,38 @@
  */
 
 static int __init ic_setup_if(void)
 {
 	struct ifreq ir;
-	struct sockaddr_in *sin = (void *) &ir.ifr_ifru.ifru_addr;
+	struct sockaddr_in *sin = (void *) &ir.ifr_addr;
 	int err;
 
 	memset(&ir, 0, sizeof(ir));
-	strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
+	strcpy(ir.ifr_name, ic_dev->name);
 	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);
 		return -1;
 	}
 	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);
 		return -1;
 	}
 	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);
 		return -1;
 	}
+	if (ic_dev_mtu) {
+		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);
+			/* Don't error out because set mtu failure, just notice the operator */
+	}
 	return 0;
 }
 
 static int __init ic_setup_routes(void)
 {
@@ -576,10 +601,11 @@
 			3,	/* Default gateway */
 			6,	/* DNS server */
 			12,	/* Host name */
 			15,	/* Domain name */
 			17,	/* Boot path */
+			26,	/* MTU */
 			40,	/* NIS domain name */
 		};
 
 		*e++ = 55;	/* Parameter request list */
 		*e++ = sizeof(ic_req_params);
@@ -777,10 +803,13 @@
 			break;
 		case 17:	/* Root path */
 			if (!root_server_path[0])
 				ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path));
 			break;
+		case 26:
+			ic_dev_mtu = ntohs(*(u16 *)(ext+1));
+			break;
 		case 40:	/* NIS Domain name (_not_ DNS) */
 			ic_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN);
 			break;
 	}
 }
@@ -1294,10 +1323,12 @@
 	printk(",\n     host=%s, domain=%s, nis-domain=%s",
 	       system_utsname.nodename, ic_domain, system_utsname.domainname);
 	printk(",\n     bootserver=%u.%u.%u.%u", NIPQUAD(ic_servaddr));
 	printk(", rootserver=%u.%u.%u.%u", NIPQUAD(root_server_addr));
 	printk(", rootpath=%s", root_server_path);
+	if (ic_dev_mtu)
+		printk(", mtu=%d", ic_dev_mtu);
 	printk("\n");
 #endif /* !SILENT */
 
 	return 0;
 }