[patch] [rfc] Re: udhcpc eating too much cpu

Bernhard Fischer rep.dot.nop at gmail.com
Thu Jan 17 11:21:38 UTC 2008


On Wed, Jan 16, 2008 at 11:28:48PM +0100, Cristian Ionescu-Idbohrn wrote:
>On Sun, 13 Jan 2008, Cristian Ionescu-Idbohrn wrote:
>
>> The problem is described here too:
>>
>>   http://archives.devshed.com/forums/networking-100/dhclient-raw-socket-2147170.html
>>
>> We noticed that too (corner cases).  udhcpc eats up to 30% cpu.
>> That happens after DISCOVER while waiting for OFFER.  udhcpc is looking
>> through every udp package.
>>
>> I also learned (from one of my collegues) that a LPF/BPF filter will
>> most likely help.
>
>[snip]
>
>> I intend to try that during the comming weeks, if noone else beats me to
>> it ;)
>
>And this is what I could come up with (attached). Besides the actual
>LPF-filter in networking/udhcp/clientsocket.c, I thought it was wise to
>move SERVER_PORT and CLIENT_PORT from networking/udhcp/options.h to
>networking/udhcp/common.h and adjust some other file(s) accordingly.  The
>rest is just whitespace damage fixes.

Can you please separate the whitespace fixes from actual changes (diff
-rdupbBw or the like to filter out the noise).

What is the size(1) change with your patch?
Can anyone confirm that this fixes the problem several of you were
experiencing?

thanks,
>
>This patch reduces udhcpc CPU-consumption (when the dhcp-server(s) is/are
>unresponsive) on our board from 10-30% down to 0% (as shown by bb-top).
>
>Besides messages like "bogous packet" and "oversized packet" (don't
>remember the exact wording and I'm too lazy to look them up again, but
>can be reproduced with DEBUG enebled and running udhcpc in the foreground)
>do no longer show up in the console.
>
>The comment in networking/udhcp/clientsocket.c gives credit to Stefan
>Rompf <sux at loplof.de>, I've shamelessly stolen the LPF/BPF-filter from.
>I hereby aknowledge his involuntary contribution to this project :)  I
>don't think there should be any copyright and/or licensing problems here.
>
>Stefan (if reachable) will probably comment.
>
>In my big comment inside networking/udhcp/clientsocket.c I'm also trying
>to pinpoint some ideas that I'm very fond of and Stefan puts words on.  I
>think those ideas (if implemented in busybox) would be a big lift for this
>project, namely:  netlink events and server reconfiguration without
>restarts, SIGHUPs, complicates scripts, resource drains especially for
>embedded systems, and so on.
>
>
>Cheers,
>
>-- 
>Cristian
>--- networking/udhcp/clientsocket.c.~1~	2006-12-20 08:30:32.000000000 +0100
>+++ networking/udhcp/clientsocket.c	2008-01-16 14:52:21.000000000 +0100
>@@ -30,23 +30,73 @@
> #include <linux/if_packet.h>
> #include <linux/if_ether.h>
> #endif
>+#include <linux/filter.h>
> 
> #include "common.h"
> 
>-
> int raw_socket(int ifindex)
> {
> 	int fd;
>-	struct sockaddr_ll sock;
>+	struct sockaddr_ll sock = {
>+		.sll_family		= AF_PACKET,
>+		.sll_protocol	= htons(ETH_P_IP),
>+		.sll_ifindex	= ifindex,
>+	};
>+
>+	/*
>+	 * Comment:
>+	 *
>+	 *	I've selected not to see LL header, so BPF doesn't see it, too.
>+	 *	The filter may also pass non-IP and non-ARP packets, but we do
>+	 *	a more complete check when receiving the message in userspace.
>+	 *
>+	 * and filter shamelessly stolen from:
>+	 *
>+	 *	http://www.flamewarmaster.de/software/dhcpclient/
>+	 *
>+	 * There are a few other interesting ideas on that page (look under
>+	 * "Motivation").  Use of netlink events is most interesting.  Think
>+	 * of various network servers listening for events and reconfiguring.
>+	 * That would obsolete sending HUP signals and/or make use of restarts.
>+	 *
>+	 * Copyright: 2006, 2007 Stefan Rompf <sux at loplof.de>.
>+	 * License: GPL v2.
>+	 */
>+	struct sock_filter filter_instr[] = {
>+		/* check for udp */
>+		BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9),
>+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 2, 0),	/* L5, L1, is UDP? */
>+		/* ugly check for arp on ethernet-like and IPv4 */
>+		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),					/* L1: */
>+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x08000604, 3, 4),	/* L3, L4 */
>+		/* skip IP header */
>+		BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0),					/* L5: */
>+		/* check udp source port */
>+		BPF_STMT(BPF_LD|BPF_H|BPF_IND, 0),
>+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SERVER_PORT, 0, 1),	/* L3, L4 */
>+		/* returns */
>+		BPF_STMT(BPF_RET|BPF_K, ~0UL),						/* L3: pass */
>+		BPF_STMT(BPF_RET|BPF_K, 0),							/* L4: reject */
>+	};
>+
>+	struct sock_fprog filter_prog = {
>+		.len	= sizeof(filter_instr) / sizeof(filter_instr[0]),
>+		.filter	= filter_instr,
>+	};
>+
>+	DEBUG("opening raw socket on ifindex %d", ifindex);
> 
>-	DEBUG("Opening raw socket on ifindex %d", ifindex);
> 	fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
>+	DEBUG("got raw socket fd %d", fd);
>+
>+	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog,
>+				sizeof(filter_prog)) < 0)
>+		bb_perror_msg_and_die("setsockopt");
>+	DEBUG("attached filter to raw socket fdr %d", fd);
> 
>-	sock.sll_family = AF_PACKET;
>-	sock.sll_protocol = htons(ETH_P_IP);
>-	sock.sll_ifindex = ifindex;
> 	xbind(fd, (struct sockaddr *) &sock, sizeof(sock));
>+	DEBUG("bound to raw socket fd %d", fd);
> 
> 	return fd;
> }
>--- networking/udhcp/common.h.~1~	2007-12-21 08:30:26.000000000 +0100
>+++ networking/udhcp/common.h	2008-01-16 14:36:29.000000000 +0100
>@@ -14,6 +14,9 @@
> 
> #define DEFAULT_SCRIPT  "/usr/share/udhcpc/default.script"
> 
>+#define SERVER_PORT		67
>+#define CLIENT_PORT		68
>+
> extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */
> 
> /*** packet.h ***/
>@@ -93,8 +96,8 @@
> int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface);
> 
> #if ENABLE_FEATURE_UDHCP_DEBUG
>-# define DEBUG(str, args...) bb_info_msg(str, ## args)
>+# define DEBUG(str, args...) bb_info_msg("### " str, ## args)
> #else
> # define DEBUG(str, args...) do {;} while (0)
> #endif
>--- networking/udhcp/dhcpc.c.~1~	2007-12-25 08:30:28.000000000 +0100
>+++ networking/udhcp/dhcpc.c	2008-01-15 16:09:32.000000000 +0100
>@@ -452,7 +452,8 @@
> 
> 			if (listen_mode == LISTEN_KERNEL)
> 				len = udhcp_recv_packet(&packet, sockfd);
>-			else len = get_raw_packet(&packet, sockfd);
>+			else
>+				len = get_raw_packet(&packet, sockfd);
> 
> 			if (len == -1) { /* error is severe, reopen socket */
> 				DEBUG("error on read, %s, reopening socket", strerror(errno));
>@@ -517,10 +518,10 @@
> #if ENABLE_FEATURE_UDHCPC_ARPING
> 					if (opt & OPT_a) {
> 						if (!arpping(packet.yiaddr,
>-							    (uint32_t) 0,
>-							    client_config.arp,
>-							    client_config.interface)
>+								(uint32_t) 0,
>+								client_config.arp,
>+								client_config.interface)
> 						) {
> 							bb_info_msg("offered address is in use "
> 								"(got ARP reply), declining");
>--- networking/udhcp/dhcprelay.c.~1~	2007-12-21 08:30:26.000000000 +0100
>+++ networking/udhcp/dhcprelay.c	2008-01-16 12:53:21.000000000 +0100
>@@ -155,12 +155,12 @@
> 	int i, n;
> 
> 	/* talk to real server on bootps */
>-	fds[0] = listen_socket(/*INADDR_ANY,*/ 67, server);
>+	fds[0] = listen_socket(/*INADDR_ANY,*/ SERVER_PORT, server);
> 	n = fds[0];
> 
> 	for (i = 1; i < num_clients; i++) {
> 		/* listen for clients on bootps */
>-		fds[i] = listen_socket(/*INADDR_ANY,*/ 67, client[i-1]);
>+		fds[i] = listen_socket(/*INADDR_ANY,*/ SERVER_PORT, client[i-1]);
> 		if (fds[i] > n)
> 			n = fds[i];
> 	}
>@@ -289,8 +289,8 @@
> 	struct sockaddr_in server_addr;
> 
> 	server_addr.sin_family = AF_INET;
>-	server_addr.sin_port = htons(67);
>+	server_addr.sin_port = htons(SERVER_PORT);
> 	if (argc == 4) {
> 		if (!inet_aton(argv[3], &server_addr.sin_addr))
> 			bb_perror_msg_and_die("didn't grok server");
>--- networking/udhcp/options.h.~1~	2007-11-30 08:30:29.000000000 +0100
>+++ networking/udhcp/options.h	2008-01-16 12:43:36.000000000 +0100
>@@ -28,9 +28,6 @@
> /*****************************************************************/
> 
> /* DHCP protocol -- see RFC 2131 */
>-#define SERVER_PORT		67
>-#define CLIENT_PORT		68
>-
> #define DHCP_MAGIC		0x63825363
> 
> 

>_______________________________________________
>busybox mailing list
>busybox at busybox.net
>http://busybox.net/cgi-bin/mailman/listinfo/busybox



More information about the busybox mailing list