lkml.org 
[lkml]   [2000]   [Aug]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
Subject[PATCH] 2.2: Refinements to CONFIG_IP_PNP
The 2.2.17pre series includes my DHCP support for CONFIG_IP_PNP
(thanks, Alan!). Subsequent experience with that patch has led
to the following refinements:

* MUCH better RFC compliance, esp. with multiple interfaces
* MUCH improved boot speed: usually too fast to notice
* Cosmetic display improvements
* More persistence before closing device, since eepro driver
is working much better lately (thanks, Dragan!)
* Accepted ip= parameters:
"on", "off", "any", "none", "dhcp", "rarp", "both" (backward compat)

and finally, something that really ought to be configurable:

* By default, IP config is DISABLED.
It is enabled by an "ip=" boot command line.

I'm posting this so people can use it, and to get comments that
might lead to its inclusion in 2.2.18.


Index: net/ipv4/Config.in
--- net/ipv4/Config.in.prev
+++ net/ipv4/Config.in Tue Aug 15 15:06:59 2000
@@ -16,5 +16,5 @@
fi
fi
-bool 'IP: kernel level autoconfiguration' CONFIG_IP_PNP
+bool 'IP: kernel-level configuration support' CONFIG_IP_PNP
if [ "$CONFIG_IP_PNP" = "y" ]; then
bool ' DHCP support' CONFIG_IP_PNP_DHCP
Index: net/ipv4/ipconfig.c
--- net/ipv4/ipconfig.c.prev
+++ net/ipv4/ipconfig.c Tue Aug 15 14:07:25 2000
@@ -75,6 +75,7 @@

/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */
-#define CONF_OPEN_RETRIES 3 /* (Re)open devices three times */
-#define CONF_SEND_RETRIES 3 /* Send requests three times */
+#define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */
+#define CONF_SEND_RETRIES 6 /* Send six requests per open */
+#define CONF_INTER_TIMEOUT (HZ/2) /* Inter-device timeout: 1/2 second */
#define CONF_BASE_TIMEOUT (HZ*2) /* Initial timeout: 2 seconds */
#define CONF_TIMEOUT_RANDOM (HZ) /* Maximum amount of randomization */
@@ -87,5 +88,5 @@
*/

-int ic_enable __initdata = 1; /* Automatic IP cfg enabled? */
+int ic_enable __initdata = 0; /* IP config enabled? */

/* Protocol choice */
@@ -130,8 +131,9 @@ static int ic_proto_have_if __initdata =

#ifdef IPCONFIG_DYNAMIC
-static volatile int ic_got_reply = 0; /* Protocol(s) we got reply from */
+static spinlock_t ic_recv_lock = SPIN_LOCK_UNLOCKED;
+static volatile int ic_got_reply __initdata = 0; /* Proto(s) that replied */
#endif
#ifdef IPCONFIG_DHCP
-static int ic_dhcp_msgtype __initdata = 0; /* Last incoming msg type */
+static int ic_dhcp_msgtype __initdata = 0; /* DHCP msg type received */
#endif

@@ -145,9 +147,10 @@ struct ic_device {
struct device *dev;
unsigned short flags;
- int able;
+ short able;
+ u32 xid;
};

-static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
-static struct device *ic_dev __initdata = NULL; /* Selected device */
+static struct ic_device *ic_first_dev __initdata = NULL; /* Open devices */
+static struct device *ic_dev __initdata = NULL; /* Selected device */

static int __init ic_open_devs(void)
@@ -186,6 +189,11 @@ static int __init ic_open_devs(void)
d->flags = oflags;
d->able = able;
+ if (able & IC_BOOTP)
+ get_random_bytes(&d->xid, sizeof(u32));
+ else
+ d->xid = 0;
ic_proto_have_if |= able;
- DBG((SELF "%s UP (able=%d)\n", dev->name, able));
+ DBG((SELF "%s UP (able=%d, xid=%08x)\n",
+ dev->name, able, d->xid));
}
*last = NULL;
@@ -387,4 +395,8 @@ ic_rarp_recv(struct sk_buff *skb, struct
unsigned long sip, tip;
unsigned char *sha, *tha; /* s for "source", t for "target" */
+ struct ic_device *d;
+
+ /* One reply at a time, please. */
+ spin_lock(&ic_recv_lock);

/* If we already have a reply, just drop the packet */
@@ -392,4 +404,11 @@ ic_rarp_recv(struct sk_buff *skb, struct
goto drop;

+ /* Find the ic_device that the packet arrived on */
+ d = ic_first_dev;
+ while (d && d->dev != dev)
+ d = d->next;
+ if (!d)
+ goto drop; /* should never happen */
+
/* If this test doesn't pass, it's not IP, or we should ignore it anyway */
if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd))
@@ -421,5 +440,5 @@ ic_rarp_recv(struct sk_buff *skb, struct
goto drop;

- /* Victory! The packet is what we were looking for! */
+ /* We have a winner! */
ic_dev = dev;
if (ic_myaddr == INADDR_NONE)
@@ -429,6 +448,10 @@ ic_rarp_recv(struct sk_buff *skb, struct

drop:
- /* and throw the packet out */
+ /* Show's over. Nothing to see here. */
+ spin_unlock(&ic_recv_lock);
+
+ /* Throw the packet out. */
kfree_skb(skb);
+
return 0;
}
@@ -438,4 +461,14 @@ drop:
* Send RARP request packet over all devices which allow RARP.
*/
+static void __init ic_rarp_send_if(struct ic_device *d)
+{
+ struct device *dev = d->dev;
+ arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
+ dev->dev_addr, dev->dev_addr);
+}
+
+/*
+ * Send RARP request package over a single interface.
+ */
static void __init ic_rarp_send(void)
{
@@ -443,9 +476,6 @@ static void __init ic_rarp_send(void)

for (d=ic_first_dev; d; d=d->next)
- if (d->able & IC_RARP) {
- struct device *dev = d->dev;
- arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
- dev->dev_addr, dev->dev_addr);
- }
+ if (d->able & IC_RARP)
+ ic_rarp_send_if(d);
}

@@ -492,6 +522,4 @@ struct bootp_pkt { /* BOOTP packet form
#define DHCPINFORM 8

-static u32 ic_bootp_xid;
-
static int ic_bootp_recv(struct sk_buff *skb, struct device *dev,
struct packet_type *pt);
@@ -517,10 +545,10 @@ static void __init
ic_dhcp_init_options(u8 *options)
{
- u8 msgtype = ((ic_dhcp_msgtype == DHCPOFFER)
- ? DHCPREQUEST : DHCPDISCOVER);
+ u8 mt = ((ic_servaddr == INADDR_NONE)
+ ? DHCPDISCOVER : DHCPREQUEST);
u8 *e = options;

#ifdef IPCONFIG_DEBUG
- printk("DHCP: Sending message type %d\n", msgtype);
+ printk("DHCP: Sending message type %d\n", mt);
#endif

@@ -530,7 +558,12 @@ ic_dhcp_init_options(u8 *options)
*e++ = 53; /* DHCP message type */
*e++ = 1;
- *e++ = msgtype;
+ *e++ = mt;
+
+ if (mt == DHCPREQUEST) {
+ *e++ = 54; /* Server ID (IP address) */
+ *e++ = 4;
+ memcpy(e, &ic_servaddr, 4);
+ e += 4;

- if (msgtype == DHCPREQUEST) {
*e++ = 50; /* Requested IP address */
*e++ = 4;
@@ -596,6 +629,4 @@ static inline void
ic_bootp_init(void)
{
- get_random_bytes(&ic_bootp_xid, sizeof(u32));
- DBG(("DHCP/BOOTP: XID=%08x\n", ic_bootp_xid));
dev_add_pack(&bootp_packet_type);
}
@@ -657,5 +688,5 @@ ic_bootp_send_if(struct ic_device *d, u3
memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
b->secs = htons(jiffies / HZ);
- b->xid = ic_bootp_xid;
+ b->xid = d->xid;

/* add DHCP options or BOOTP extensions */
@@ -757,10 +788,21 @@ static int __init ic_bootp_recv(struct s
struct bootp_pkt *b = (struct bootp_pkt *) skb->nh.iph;
struct iphdr *h = &b->iph;
+ struct ic_device *d;
int len;

+ /* One reply at a time, please. */
+ spin_lock(&ic_recv_lock);
+
/* If we already have a reply, just drop the packet */
if (ic_got_reply)
goto drop;

+ /* Find the ic_device that the packet arrived on */
+ d = ic_first_dev;
+ while (d && d->dev != dev)
+ d = d->next;
+ if (!d)
+ goto drop; /* should never happen */
+
/* Check whether it's a BOOTP packet */
if (skb->pkt_type == PACKET_OTHERHOST ||
@@ -784,7 +826,7 @@ static int __init ic_bootp_recv(struct s
/* Is it a reply to our BOOTP request? */
len = ntohs(b->udph.len) - sizeof(struct udphdr);
- if (len < 300 || /* See RFC 951:2.1 */
+ if (len < 300 || /* See RFC 951:2.1 */
b->op != BOOTP_REPLY ||
- b->xid != ic_bootp_xid) {
+ b->xid != d->xid) {
printk("?");
goto drop;
@@ -799,5 +841,5 @@ static int __init ic_bootp_recv(struct s

u32 server_id = INADDR_NONE;
- ic_dhcp_msgtype = 0;
+ int mt = 0;

ext = &b->exten[4];
@@ -812,5 +854,5 @@ static int __init ic_bootp_recv(struct s
case 53: /* Message type */
if (opt[1])
- ic_dhcp_msgtype = opt[2];
+ mt = opt[2];
break;
case 54: /* Server ID (IP address) */
@@ -822,9 +864,13 @@ static int __init ic_bootp_recv(struct s

#ifdef IPCONFIG_DEBUG
- printk("DHCP: Got message type %d\n", ic_dhcp_msgtype);
+ printk("DHCP: Got message type %d\n", mt);
#endif

- switch (ic_dhcp_msgtype) {
+ switch (mt) {
case DHCPOFFER:
+ /* While in the process of accepting one offer,
+ ignore all others. */
+ if (ic_myaddr != INADDR_NONE)
+ goto drop;
/* Let's accept that offer. */
ic_myaddr = b->your_ip;
@@ -834,5 +880,5 @@ static int __init ic_bootp_recv(struct s
printk(" by server %s\n", in_ntoa(ic_servaddr));
#endif
- goto drop;
+ break;

case DHCPACK:
@@ -847,4 +893,6 @@ static int __init ic_bootp_recv(struct s
}

+ ic_dhcp_msgtype = mt;
+
#endif /* IPCONFIG_DHCP */

@@ -860,4 +908,5 @@ static int __init ic_bootp_recv(struct s
}

+ /* We have a winner! */
ic_dev = dev;
ic_myaddr = b->your_ip;
@@ -870,6 +919,10 @@ static int __init ic_bootp_recv(struct s

drop:
- /* and throw the packet out */
+ /* Show's over. Nothing to see here. */
+ spin_unlock(&ic_recv_lock);
+
+ /* Throw the packet out. */
kfree_skb(skb);
+
return 0;
}
@@ -888,6 +941,6 @@ static int __init ic_dynamic(void)
{
int retries;
- unsigned long timeout, jiff;
- unsigned long start_jiffies;
+ struct ic_device *d;
+ unsigned long start_jiffies, timeout, jiff;
int do_bootp = ic_proto_have_if & IC_BOOTP;
int do_rarp = ic_proto_have_if & IC_RARP;
@@ -937,10 +990,12 @@ static int __init ic_dynamic(void)
* applies.. - AC]
*/
- printk(KERN_NOTICE "Sending %s%s%s requests ",
+ printk(KERN_NOTICE "Sending %s%s%s requests .",
do_bootp
? ((ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP") : "",
(do_bootp && do_rarp) ? " and " : "",
do_rarp ? "RARP" : "");
+
start_jiffies = jiffies;
+ d = ic_first_dev;
retries = CONF_SEND_RETRIES;
get_random_bytes(&timeout, sizeof(timeout));
@@ -948,23 +1003,24 @@ static int __init ic_dynamic(void)
for(;;) {
#ifdef IPCONFIG_BOOTP
- if (do_bootp)
- ic_bootp_send(jiffies - start_jiffies);
+ if (do_bootp && (d->able & IC_BOOTP))
+ ic_bootp_send_if(d, jiffies - start_jiffies);
#endif
#ifdef IPCONFIG_RARP
- if (do_rarp)
- ic_rarp_send();
+ if (do_rarp && (d->able & IC_RARP))
+ ic_rarp_send_if(d);
#endif
- printk(".");

- jiff = jiffies + timeout;
+ jiff = jiffies + (d->next ? CONF_INTER_TIMEOUT : timeout);
while (jiffies < jiff && !ic_got_reply)
;
+
#ifdef IPCONFIG_DHCP
+ /* DHCP isn't done until we get a DHCPACK. */
if ((ic_got_reply & IC_BOOTP)
&& (ic_proto_enabled & IC_USE_DHCP)
&& ic_dhcp_msgtype != DHCPACK)
{
- printk(",");
ic_got_reply = 0;
+ printk(",");
continue;
}
@@ -976,4 +1032,7 @@ static int __init ic_dynamic(void)
}

+ if ((d = d->next))
+ continue;
+
if (! --retries) {
printk(" timed out!\n");
@@ -981,7 +1040,11 @@ static int __init ic_dynamic(void)
}

+ d = ic_first_dev;
+
timeout = timeout CONF_TIMEOUT_MULT;
if (timeout > CONF_TIMEOUT_MAX)
timeout = CONF_TIMEOUT_MAX;
+
+ printk(".");
}

@@ -998,5 +1061,6 @@ static int __init ic_dynamic(void)
return -1;

- printk(SELF "Got %s answer from %s\n",
+ printk(SELF "%s: Got %s answer from %s\n",
+ ic_dev->name,
((ic_got_reply & IC_RARP) ? "RARP"
: (ic_proto_enabled & IC_USE_DHCP) ? "DHCP" : "BOOTP"),
@@ -1168,5 +1232,5 @@ int __init ip_auto_config(void)
*/
printk(SELF "Complete:");
- printk("\n device=%s", ic_dev->name);
+ printk( "\n if=%s", ic_dev->name);
printk(", addr=%s", in_ntoa(ic_myaddr));
printk(", mask=%s", in_ntoa(ic_netmask));
@@ -1200,12 +1264,12 @@ int __init ip_auto_config(void)
* <device> - use all available devices
* <PROTO>:
- * dhcp|bootp|rarp - use given protocol
- * both or empty - use both BOOTP and RARP (not DHCP)
- * off or none - don't do autoconfig at all
+ * off|none - don't do autoconfig at all (DEFAULT)
+ * on|any - use any configured protocol
+ * dhcp|bootp|rarp - use only the specified protocol
+ * both - use both BOOTP and RARP (not DHCP)
*/
static int __init ic_proto_name(char *name)
{
- if (!strcmp(name, "off") || !strcmp(name, "none")) {
- ic_proto_enabled = 0;
+ if (!strcmp(name, "on") || !strcmp(name, "any")) {
return 1;
}
@@ -1242,8 +1306,8 @@ void __init ip_auto_config_setup(char *a
int num = 0;

- if (!strcmp(addrs, "off") || !strcmp(addrs, "none")) {
- ic_enable = 0;
+ ic_enable = (*addrs && strcmp(addrs, "off") && strcmp(addrs, "none"));
+ if (!ic_enable)
return;
- }
+
if (ic_proto_name(addrs))
return;
--
Chip Salzenberg - a.k.a. - <chip@valinux.com>
"I wanted to play hopscotch with the impenetrable mystery of existence,
but he stepped in a wormhole and had to go in early." // MST3K
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.041 / U:12.176 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site