Messages in this thread Patch in this message |  | | Date | Thu, 12 Sep 1996 17:00:48 +1200 (NZST) | From | Oliver Jowett <> | Subject | SOCK_PACKET bug with ETH_P_ALL? |
| |
I run 3 diald processes on a Linux box sitting on a pretty busy ethernet. I recently noticed that each of these dialds was using 1-3% cpu time, even when the proxies were idle. Turning on promisc mode on eth0 pushed that through the roof. 'strace'ing a diald produced results along the line of:
select(100, [1 2 4], NULL, NULL, {0, 990000}) = 1 (in [2], left {0, 710000}) recvfrom(2, "\377\377\377\377\377\377\252\0\4"..., 4096, 0, {sun_family=AF_UNIX, sun_path="eth0"}, [16]) = 142 time(NULL) = 842498155 time(NULL) = 842498155 select(100, [1 2 4], NULL, NULL, {0, 710000}) = 1 (in [2], left {0, 520000}) recvfrom(2, "\377\377\377\377\377\377\252\0\4"..., 4096, 0, {sun_family=AF_UNIX, sun_path="eth0"}, [16]) = 111 time(NULL) = 842498155 time(NULL) = 842498155 select(100, [1 2 4], NULL, NULL, {0, 520000}) = 1 (in [2], left {0, 190000}) recvfrom(2, "\377\377\377\377\377\377\0\200\243"..., 4096, 0, {sun_family=AF_UNIX, sun_path="eth0"}, [16]) = 110 time(NULL) = 842498155 time(NULL) = 842498155
(etc)
It looks like the snoop device is still receiving packets from eth0, despite the fact that descriptor 2, a SOCK_PACKET socket, has successfully called bind() to bind to the slip proxy.
Looking in net/core/dev.c, it looks like net_bh is forwarding packets that it shouldn't - it forwards packets to a packet-capture function with protocol ETH_P_ALL regardless of the value of ptype->dev.
I changed this to check the device, and the dialds magically went to 0% cpu :) ... a patch is attached (against 2.0.14, but I didn't see any changes to this bit of code in 15-18). I did a grep for ETH_P_ALL and the kernel code doesn't seem to use it, so hopefully this doesn't break anything else.
Is it worth moving the ptype_all list for sniffers bound to a specific device into the device struct? The current setup means that such a sniffer will cause a check of the entire ptype_all list for every packet received on _any_ device - which could become a problem with eg. multiple dialds (large ptype_all list) and a busy ethernet.
Oliver. (oliver@sa-search.massey.ac.nz, in case sendmail decides to mangle it) --- linux/net/core/dev.c.old Thu Sep 12 15:18:37 1996 +++ linux/net/core/dev.c Thu Sep 12 15:28:13 1996 @@ -654,13 +654,17 @@ pt_prev = NULL; for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next) { - if(pt_prev) + /* Make sure we only pass on packets for the right device */ + if (!ptype->dev || ptype->dev==skb->dev) { - struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); - if(skb2) - pt_prev->func(skb2,skb->dev, pt_prev); - } - pt_prev=ptype; + if(pt_prev) + { + struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC); + if(skb2) + pt_prev->func(skb2,skb->dev, pt_prev); + } + pt_prev=ptype; + } } for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) |  |