From owner-freebsd-hackers Tue Aug 18 04:32:35 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id EAA07941 for freebsd-hackers-outgoing; Tue, 18 Aug 1998 04:32:35 -0700 (PDT) (envelope-from owner-freebsd-hackers@FreeBSD.ORG) Received: from muffin.arcadia.spb.ru (arcadia-gw.infopro.spb.su [195.201.255.65]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id EAA07915 for ; Tue, 18 Aug 1998 04:32:27 -0700 (PDT) (envelope-from fetch@muffin.arcadia.spb.ru) Received: (from root@localhost) by muffin.arcadia.spb.ru (8.9.1/8.8.6) id PAA06709 for freebsd-hackers@freebsd.org.smtp; Tue, 18 Aug 1998 15:46:08 +0400 (MSD) Received: (from fetch@localhost) by muffin.arcadia.spb.ru (8.9.1/8.8.6) id PAA06670 for freebsd-hackers@freebsd.org; Tue, 18 Aug 1998 15:46:06 +0400 (MSD) From: Andrey Alekseyev Message-Id: <199808181146.PAA06670@muffin.arcadia.spb.ru> Subject: problem with ll cloned routes To: freebsd-hackers@FreeBSD.ORG Date: Tue, 18 Aug 1998 15:46:06 +0400 (MSD) X-Mailer: ELM [version 2.4ME+ PL31 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG Hello, Please be patient to the things that I'm going to describe below, I may be wrong (in fact I guess I'm wrong with the fix) I've recently found an annoying feature of internal routing table managing in FreeBSD 2.2.6-RELEASE (posted two lame problem reports on this yet - #7578, wish someone will remove it from there). First the problem itself: when interface is deleted (or alias on an interface is deleted) a corresponding route to network that was added for this interface is deleted also (it's quite reasonable and what everyone expects when deleting an interface). Well, but link layer cloned routes associated with this interface are not deleted. They remain intact and what is worst apparently contain pointer to the previous struct ifaddr, that itself contains old interface information. So, when you delete an alias on interface and for example set another (neighboring) ip address on it and there is a route to some host cloned from the old alias, packets to that host will go out with the old alias ip address of used interface. Because when doing rt_alloc for ip_output, it will find the old route matching and ip_output will happily retrieve an old (non-existing so far) interface address from the pointer in this rtentry and send packets with the old (non-existing) ip address. Well, now the technical details I've found. Please, if I'm wrong could someone please explain me where I mistake. Creating a route: 1. interface is being configured. On some step of this configuration route to corresponding network is added (I'm now talking about ether interface) 2. some packet is ready to be out on this interface. In ip_output rtalloc_ign(ro, RTF_PRCLONING) is called to find route to the destination 3. rtalloc_ign calls rtalloc1 that finds route to network created when corresponding interface was created and then tries to allocate route to destination 4. it calls rtrequest 5. rtrequest allocates a new rtentry and on some internal step will call ifa->ifa_rtrequest for used interface (arp_rtrequest) 6. finally route is ready and has the flag RTF_WASCLONED (route to network from which it was cloned has the flag RTF_CLONING on it) 7. packet is out Now deleting an alias or interface configuraion at all: 1. interface losts its address. On some step in_ifscrub is called that will try to remove any route to the interface address that is being deleted 2. in_ifscrub calls rtinit with RTM_DELETE parameter 3. rtinit on some step call rtrequest with cmd = RTM_DELETE 4. what happens in rtrequest_delete is a little bit strange - it doesn't do anything that will delete routes cloned from this route being deleted (not protocol-cloned). I.e. it apparently doesn't even try to locate routing entries cloned from this route. Am I wrong and simply didn't notice such code? If so, I'd appreciate it very much if you point me where is the code that will try to remove cloned routing entries, I'm very curious about it. Well, in fact I'm pretty sure that such code must exist there but I didn't find it and so didn't find why it doesn't work. So the only thing that came to mind is the following: in rtrequest_makeroute when checking if the route is protocol-cloned check also if it's ll cloned and create a link to parent route in this case also, then in rtrequest_delete when checking for cloned routes look also for any ll cloned routes if there is RTF_CLONING flag on the route we are deleting. This is the only trick I developed against that problem and apparently it seems functional, also there comes another problem that confuses me: netstat doesn't show ll cloned entries with this fix and that's because it assumes that having non-zero rt_parent pointer means the route is _protocol_cloned_. Well, I'm a little bit messed with that code and the only thing I definitely want to know is - where is in fact the right code that will clear ll cloned route entries and what is then the right mechanism for keeping, creating and cleaning such routes. I'll appreciate any comments on the above posting because I got very curious about all this routing implementation when started to look at the code. Well, why do I think I'm wrong with the patch. Because it makes ll cloned routes and protocol cloned routes look similar (don't think netstat is wrong not showing me routes with parent by default). Also, route.c was not changed since 2.2.2-RELEASE and it seems to me there was no such problem in 2.2.2, unfortunately can't verify it right now. Now the patched route.c --- route.c Tue Aug 18 13:32:27 1998 +++ route.c.orig Tue Aug 18 13:30:29 1998 @@ -450,7 +450,7 @@ * Now search what's left of the subtree for any cloned * routes which might have been formed from this node. */ - if ((rt->rt_flags & (RTF_CLONING | RTF_PRCLONING)) && netmask) { + if ((rt->rt_flags & RTF_PRCLONING) && netmask) { rnh->rnh_walktree_from(rnh, dst, netmask, rt_fixdelete, rt); } @@ -575,8 +575,7 @@ if (req == RTM_RESOLVE) { rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ - if ((*ret_nrt)->rt_flags & - (RTF_CLONING | RTF_PRCLONING)) { + if ((*ret_nrt)->rt_flags & RTF_PRCLONING) { rt->rt_parent = (*ret_nrt); (*ret_nrt)->rt_refcnt++; } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message