[PATCH 0/4] ipv4: fix problems with same IPs in many subnets
From: Julian Anastasov <ja@ssi.bg>
Date: 2011-03-18 23:06:50
Here are some changes for the IPv4 addresses and the routes we delete for setups using same primary or secondary IPs in many subnets on device. They are made for net-next from March 13. Attached is a test script that tests the kernel for the observed problems and validates some operations. The same script should be available here: http://www.ssi.bg/~ja/test_ipdel.sh Can be run before and after patching to compare results. Usage: # Tune script: device, etc # Run test with generating sorted listings, useful for diff -u ./test_ipdel.sh list > out1 # Run test with brief output ./test_ipdel.sh As there some questions on using same IPs in different subnets, here is some info and the current problems I'm seeing. __inet_insert_ifa() considers IPs as secondary when they use same prefixlen (mask) as existing primary IP. So, it is perfectly valid for some device: - to have two primary IFAs for same IP "P1" but with different masks "M1" and "M2", probably with different scope (visibility for the defined subnet): IFA1: P1/M1 IFA2: P1/M2 - when adding secondary IPs the same rule applies: IFA3: S1/M1, can use primary P1 from IFA1 IFA4: S1/M2, can use primary P1 from IFA2 inet_ifa_byprefix() can correctly match IFA1 or IFA2 by address (P1) and mask (M1 or M2). To summarize for IPs: the combination of device, IP address and prefixlen (mask) should be unique. Same IPs can be used in many overlapping subnets. The IPs for device are always saved in sorted form: all primaries before all secondaries, the primaries are sorted by decreasing scope, primaries with same scope are in order of adding, the secondaries are in random (adding) order but with same scope as their primary. When addresses are converted to local or broadcast routes we have: - All routes are added with prefsrc. The prefsrc is the primary address. As the combination of local IP and its primary address is unique only for its subnet if we use the same IPs in another subnet it is possible to try to add the same routes twice resulting in duplication. But only one route is created in such case and on deletion we should be careful not to delete routes that are also required for the same IPs in different subnet. - When creating local or broadcast route for the added address we ignore the prefixlen. As result, the combination of address (FIB node=IP/32), primary IP (fib_prefsrc) and device (fib_info, NH) should be unique. The above IFA1 and IFA2 will try to create same local route: local P1/32 via dev DEV ... src P1 and the result will be single route. IFA3 and IFA4 will add single route too: local S1/32 via dev DEV ... src P1 When addresses are deleted we should remove exactly the routes that were created for our IFA but with checks for duplication in another subnet. The problems in current code: - fib_del_ifaddr() unconditionally tries to remove the subnet route when deleting primary IFA. The problem is that if prefixlen is 32 we need more checks, eg. if this IP is still used in another subnet. - fib_del_ifaddr() forgets to match the primary address for every IFA that is checked. As result, routes for deleted secondary IFAs can remain until their primary IFA is deleted just because the same address is used in another subnet but with different primary IP. - fib_table_delete() does not match the prefsrc, so if there are many routes that differ in prefsrc, always the first route is deleted. By this way, we can not remove the right route for the deleted IFAs. - On secondary address promotion, when deleting the primary address all routes with such prefsrc are currently expected to be deleted by fib_sync_down_addr without sending events for the remaining secondaries. But as fib_sync_down_addr calling depends on other subnets and even on other devices we can leak the routes. The following patches fix the above problems. I don't try to forbid same IPs to be used in multiple subnets because it is perfectly valid subnets to overlap. As patch 2 needs to know the primary IP (but not its IFA) for every secondary address, another implementation is possible where new field ifa_primary can cache the primary IP used for the IFA. Then we will avoid the inet_ifa_byprefix calls when we walk secondaries from different subnets. For now I'm using a 'same_prefsrc' flag that detects if multiple subnets use same primary IP, so such lookups are avoided later for the secondaries for the common case when same IPs are not used in more than one subnet. Regards -- Julian Anastasov [off-list ref]
Attachments
- test_ipdel.sh [application/x-sh] 3655 bytes · preview