Add support to honor MTU settings from DHCP during netboot. trunk
authorcyber <cyber@NetBSD.org>
Mon, 04 Oct 2010 23:48:22 +0000
branchtrunk
changeset 193844 1c1fa12e1784
parent 193843 34d7fb29a651
child 193845 78434e77f031
Add support to honor MTU settings from DHCP during netboot. Defines IP_MIN_MTU as 576. Glanced over quickly by martin@ and joerg@.
sys/nfs/nfs_boot.c
sys/nfs/nfs_bootdhcp.c
sys/nfs/nfsdiskless.h
--- a/sys/nfs/nfs_boot.c	Mon Oct 04 22:31:53 2010 +0000
+++ b/sys/nfs/nfs_boot.c	Mon Oct 04 23:48:22 2010 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_boot.c,v 1.79 2009/03/04 06:56:25 nisimura Exp $	*/
+/*	$NetBSD: nfs_boot.c,v 1.80 2010/10/04 23:48:22 cyber Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1997 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_boot.c,v 1.79 2009/03/04 06:56:25 nisimura Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_boot.c,v 1.80 2010/10/04 23:48:22 cyber Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -91,6 +91,8 @@
 int nfs_boot_bootstatic = 1; /* BOOTSTATIC enabled (default) */
 #endif
 
+#define IP_MIN_MTU 576
+
 /* mountd RPC */
 static int md_mount(struct sockaddr_in *mdsin, char *path,
 	struct nfs_args *argp, struct lwp *l);
@@ -155,6 +157,12 @@
 		return (error);
 
 	/*
+	 * Set MTU if passed
+	 */
+	if (nd->nd_mtu >= IP_MIN_MTU )
+		nfs_boot_setmtu(nd->nd_ifp, nd->nd_mtu, lwp);
+	
+	/*
 	 * If the gateway address is set, add a default route.
 	 * (The mountd RPCs may go across a gateway.)
 	 */
@@ -236,6 +244,48 @@
 	return (error);
 }
 
+void
+nfs_boot_setmtu(struct ifnet *ifp, int mtu, struct lwp *lwp)
+{
+	struct socket *so;
+	struct ifreq ireq;
+	int error;
+
+	memset(&ireq, 0, sizeof(ireq));
+	memcpy(ireq.ifr_name, ifp->if_xname, IFNAMSIZ);
+
+	/*
+	 * Get a socket to use for various things in here.
+	 * After this, use "goto out" to cleanup and return.
+	 */
+	error = socreate(AF_INET, &so, SOCK_DGRAM, 0, lwp, NULL);
+	if (error) {
+		printf("setmtu: socreate, error=%d\n", error);
+		return;
+	}
+
+	/*
+	 * Get structure, set the new MTU, push structure.
+	 */
+	error = ifioctl(so, SIOCGIFMTU, (void *)&ireq, lwp);
+	if (error) {
+		printf("setmtu: GIFMTU, error=%d\n", error);
+		goto out;
+	}
+
+	ireq.ifr_mtu = mtu;
+
+	error = ifioctl(so, SIOCSIFMTU, &ireq, lwp);
+	if (error) {
+		printf("setmtu: SIFMTU, error=%d\n", error);
+		goto out;
+	}
+
+out:
+	soclose(so);
+	return;
+}
+
 int
 nfs_boot_setaddress(struct ifnet *ifp, struct lwp *lwp,
 		uint32_t addr, uint32_t netmask, uint32_t braddr)
--- a/sys/nfs/nfs_bootdhcp.c	Mon Oct 04 22:31:53 2010 +0000
+++ b/sys/nfs/nfs_bootdhcp.c	Mon Oct 04 23:48:22 2010 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_bootdhcp.c,v 1.51 2009/07/10 12:16:31 roy Exp $	*/
+/*	$NetBSD: nfs_bootdhcp.c,v 1.52 2010/10/04 23:48:22 cyber Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1997 The NetBSD Foundation, Inc.
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_bootdhcp.c,v 1.51 2009/07/10 12:16:31 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_bootdhcp.c,v 1.52 2010/10/04 23:48:22 cyber Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs_boot.h"
@@ -176,6 +176,8 @@
 #define TAG_DOMAIN_NAME		((unsigned char)  15)
 #define TAG_SWAP_SERVER		((unsigned char)  16)
 #define TAG_ROOT_PATH		((unsigned char)  17)
+/* RFC 2132 */
+#define TAG_INTERFACE_MTU	((unsigned char)  26)
 /* End of stuff from bootp.h */
 
 #ifdef NFS_BOOT_DHCP
@@ -203,6 +205,8 @@
 #define DHCPRELEASE 7
 #endif
 
+#define IP_MIN_MTU 576
+
 #ifdef NFS_BOOT_DHCP
 #define BOOTP_SIZE_MAX	(sizeof(struct bootp)+312-64)
 #else
@@ -453,13 +457,14 @@
 	int vcilen;
 	
 	*area++ = TAG_PARAM_REQ;
-	*area++ = 6;
+	*area++ = 7;
 	*area++ = TAG_SUBNET_MASK;
 	*area++ = TAG_GATEWAY;
 	*area++ = TAG_HOST_NAME;
 	*area++ = TAG_DOMAIN_NAME;
 	*area++ = TAG_ROOT_PATH;
 	*area++ = TAG_SWAP_SERVER;
+	*area++ = TAG_INTERFACE_MTU;
 
 	/* Insert a NetBSD Vendor Class Identifier option. */
 	snprintf(vci, sizeof(vci), "%s:%s:kernel:%s", ostype, MACHINE,
@@ -699,6 +704,7 @@
 	char *myname;	/* my hostname */
 	char *mydomain;	/* my domainname */
 	char *rootpath;
+	uint16_t myinterfacemtu;
 	int mynamelen;
 	int mydomainlen;
 	int rootpathlen;
@@ -716,6 +722,8 @@
 	rootserver = bootp->bp_siaddr;
 	/* assume that server name field is not overloaded by default */
 	overloaded = 0;
+	/* MTU can't be less than IP_MIN_MTU, set to 0 to indicate unset */
+	myinterfacemtu = 0;
 
 	p = &bootp->bp_vend[4];
 	limit = ((u_char*)bootp) + replylen;
@@ -776,6 +784,15 @@
 			rootpath = p;
 			rootpathlen = len;
 			break;
+		    case TAG_INTERFACE_MTU:
+			if (len != 2) {
+				printf("nfs_boot: interface-mtu len != 2 (%d)",
+					len);
+				break;
+			}
+			memcpy(&myinterfacemtu, p, 2);
+			myinterfacemtu = ntohs(myinterfacemtu);
+			break;
 		    case TAG_SWAP_SERVER:
 			/* override NFS server address */
 			if (len < 4) {
@@ -831,6 +848,10 @@
 		printf("nfs_boot: gateway=%s\n", inet_ntoa(nd->nd_gwip));
 		*flags |= NFS_BOOT_HAS_GWIP;
 	}
+	if (myinterfacemtu >= IP_MIN_MTU) {
+		nd->nd_mtu = myinterfacemtu;
+		printf("nfs_boot: mtu=%d\n", nd->nd_mtu);
+	}
 
 	/*
 	 * Store the information about our NFS root mount.
--- a/sys/nfs/nfsdiskless.h	Mon Oct 04 22:31:53 2010 +0000
+++ b/sys/nfs/nfsdiskless.h	Mon Oct 04 23:48:22 2010 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfsdiskless.h,v 1.29 2008/10/27 10:58:23 cegger Exp $	*/
+/*	$NetBSD: nfsdiskless.h,v 1.30 2010/10/04 23:48:23 cyber Exp $	*/
 
 /*-
  * Copyright (c) 1995, 1997 The NetBSD Foundation, Inc.
@@ -56,6 +56,7 @@
 	struct in_addr nd_myip; /* My IP address */
 	struct in_addr nd_mask; /* My netmask */
 	struct in_addr nd_gwip; /* My gateway */
+	int nd_mtu;		/* Interface MTU */
 	/* Information for each mount point we need. */
 	struct nfs_dlmount nd_root; 	/* Mount info for root */
 #ifdef TFTPROOT
@@ -65,11 +66,12 @@
 };
 
 #ifdef _KERNEL
-int nfs_boot_init (struct nfs_diskless *nd, struct lwp *lwp);
-void nfs_boot_cleanup (struct nfs_diskless *nd, struct lwp *lwp);
+int nfs_boot_init (struct nfs_diskless *, struct lwp *);
+void nfs_boot_cleanup (struct nfs_diskless *, struct lwp *);
 int nfs_boot_ifupdown (struct ifnet *, struct lwp *, int);
 int nfs_boot_setaddress (struct ifnet *, struct lwp *,
 			     uint32_t, uint32_t, uint32_t);
+void nfs_boot_setmtu (struct ifnet *, int, struct lwp *);
 int nfs_boot_deladdress (struct ifnet *, struct lwp *, uint32_t);
 void nfs_boot_flushrt (struct ifnet *);
 int nfs_boot_setrecvtimo (struct socket *);