panic: assertion: _ifac->ifa_magic == IFA_CONTAINER_MAGIC in _IFAFREE

Sepherosa Ziehau sepherosa at
Mon Mar 17 07:09:37 PDT 2008

On Mon, Mar 17, 2008 at 11:06 AM, YONETANI Tomokazu
<qhwt+dfly at> wrote:
> On Sun, Mar 16, 2008 at 08:09:17PM +0800, Sepherosa Ziehau wrote:
>  > On Sun, Mar 16, 2008 at 6:07 PM, YONETANI Tomokazu <qhwt+dfly at> wrote:
>  > > Hello.
>  > >  Just caught a panic while playing with NFS mounted git tree
>  > >  (but I cannot reliably reproduce it after that):
>  >
>  > dst address of a UDP packet is changed, which changes port/addr hash
>  > too, but old route entry was not allocated on the current CPU.  Since
>  > the box only contains 2 CPUs, after the l{port,addr}/f{port,addr}
>  > hash, the problem probably will not show itself ;).  Please run
>  > following test program several times and then unload the NIC module to
>  > see whether you could reproduce the problem (if you have TCP
>  > connections too, you will have to wait 2MSL):
>  >
>  I've been trying to reproduce it but so far unsuccessful...

I have changed this test program a little bit.  Run it in following way:
. /test_udp remote_ip

If it paused, then on the other term:
ifconfig iface_local down
And kill test_udp, if you don't have TCP connection, the panic should
happen immediately.

Though the panic place is different, but the root cause should be same:
Initially UDP socket is neither connected nor bound, thus f{addr,port}
and l{addr,port} in pcb are 0.  Sending the first datagram on this
socket will be dispatched to CPU0.  Then lport is chosen in
udp_output() and route entry is allocated on CPU0.  If (lport >> 8 &
1) is 1 on a 2 CPU box, then rest of socket operation will happen on
CPU1, e.g. sending to different faddr will cause route entry allocated
on CPU0 be freed on CPU1.

I think we need to fix following entry points:
1) udp_output(): after ip_output() if old_lport==0 and
mycpuid!=udp_addrcpu(inpcb addr/port pair) then free inpcb's route
2) udp_connect(): this function always happens on CPU0, so if
udp_addrcpu(inpcb addr/port pair)!=mycpuid(0 here), then we need to
free inpcb's route entry
3) udp_disconnect(): at the end of it, if mycpuid!=udp_addrcpu(inpcb
addr/port pair) then free inpcb's route entry

I may miss some entry points here, so please point them out to me, if
some pop up in your mind.

Best Regards,

Live Free or Die

More information about the Bugs mailing list