Hello Dave,
Long time back, I had posted about an issue with ip address deletion.
Summary of the problem :
I added the dummy device addresses in the following sequence:
ip addr add 10.3.3.3/8 dev dummy0
ip addr add 10.3.3.3/32 dev dummy0
ifconfig dummy0 10.3.3.3/32 down
ip addr show dummy0
2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noqueue
link/ether 8a:d8:bd:26:14:ab brd ff:ff:ff:ff:ff:ff
inet 10.3.3.3/32 scope global dummy0
The prefixes doesn't matter. Original post can be found here ->
http://www.uwsg.iu.edu/hypermail/linux/net/0503.2/0000.html
Thomas Graf had pointed to a patch which was queued by you, which could
fix the issue ->
http://www.uwsg.iu.edu/hypermail/linux/net/0503.2/0002.html
( The patch has been moved from the link given in the mail. I have
attached it here for convenience. )
But, the patch hasn't gone in and I am still seeing the problem on
2.6.19 :(.. I have tested this patch on 2.6.19 and if fixes the issue there.
Could you please push this patch ?
Thanks,
Suzuki
diff -Nru linux-2.6.11-bk3.orig/include/linux/inetdevice.h linux-2.6.11-bk3/include/linux/inetdevice.h
--- linux-2.6.11-bk3.orig/include/linux/inetdevice.h 2005-03-08 13:10:37.000000000 +0100
+++ linux-2.6.11-bk3/include/linux/inetdevice.h 2005-03-08 16:29:27.000000000 +0100
@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/timer.h>
+#include <linux/rtnetlink.h>
struct ipv4_devconf
{
@@ -131,6 +132,25 @@
return 0;
}
+static inline int inet_ifa_match_local_prefixlen(struct ifaddrmsg *ifm,
+ struct in_ifaddr *ifa)
+{
+ int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
+
+ /*
+ * Since the prefix length hasn't been taken into account in
+ * previous kernel versions, parts of the userspace rely on the fact
+ * that the deletion of an address without specifying a prefix works.
+ * We cannot break this and thus a prefix length of 32 still represents
+ * a wildcard if no exact match is requested.
+ */
+ if (real_prefixlen != 32 || ifm->ifa_prefixlen & IFA_PREFIX_EXACT_DEL)
+ if (real_prefixlen != ifa->ifa_prefixlen)
+ return 0;
+
+ return 1;
+}
+
#define for_primary_ifa(in_dev) { struct in_ifaddr *ifa; \
for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next)
diff -Nru linux-2.6.11-bk3.orig/include/linux/rtnetlink.h linux-2.6.11-bk3/include/linux/rtnetlink.h
--- linux-2.6.11-bk3.orig/include/linux/rtnetlink.h 2005-03-08 16:28:04.000000000 +0100
+++ linux-2.6.11-bk3/include/linux/rtnetlink.h 2005-03-08 14:17:49.000000000 +0100
@@ -396,6 +396,19 @@
#define IFA_MAX (__IFA_MAX - 1)
+/*
+ * Quirk for IPv4 address deletion to allow exact deletion of equal
+ * addresses varying only in prefix length. A explicit exact comparison
+ * of the prefix length will only be done if IFA_PREFIX_EXACT_DEL is
+ * ORed to ifa_prefixlen.
+ *
+ * Note: This special treatment is only understood while deleting
+ * addresses and will lead to unexpected behaviour if used
+ * otherwise.
+ */
+#define IFA_PREFIX_EXACT_DEL 0x40
+#define IFA_REAL_DEL_PREFIX(l) ((l) & 0x3f)
+
/* ifa_flags */
#define IFA_F_SECONDARY 0x01
diff -Nru linux-2.6.11-bk3.orig/net/ipv4/devinet.c linux-2.6.11-bk3/net/ipv4/devinet.c
--- linux-2.6.11-bk3.orig/net/ipv4/devinet.c 2005-03-08 13:10:44.000000000 +0100
+++ linux-2.6.11-bk3/net/ipv4/devinet.c 2005-03-08 16:29:49.000000000 +0100
@@ -389,6 +389,7 @@
struct in_device *in_dev;
struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
struct in_ifaddr *ifa, **ifap;
+ int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
ASSERT_RTNL();
@@ -399,12 +400,13 @@
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
ifap = &ifa->ifa_next) {
if ((rta[IFA_LOCAL - 1] &&
+ (!inet_ifa_match_local_prefixlen(ifm, ifa) ||
memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
- &ifa->ifa_local, 4)) ||
+ &ifa->ifa_local, 4))) ||
(rta[IFA_LABEL - 1] &&
rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
(rta[IFA_ADDRESS - 1] &&
- (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
+ (real_prefixlen != ifa->ifa_prefixlen ||
!inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
ifa))))
continue;