Re: [PATCH] [IPV4] Fix secondary IP addresses after promotion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* Patrick McHardy <[email protected]> 2005-11-05 01:34
> Brian Pomerantz wrote:
> >When 3 or more IP addresses in the same subnet exist on a device and the
> >first one is removed, only the promoted IP address can be reached.  Just
> >after promotion of the next IP address, this fix spins through any more
> >IP addresses on the interface and sends a NETDEV_UP notification for
> >that address.  This repopulates the FIB with the proper route
> >information.
> >
> >@@ -294,7 +294,13 @@ static void inet_del_ifa(struct in_devic
> > 		/* not sure if we should send a delete notify first? */
> > 		promote->ifa_flags &= ~IFA_F_SECONDARY;
> > 		rtmsg_ifa(RTM_NEWADDR, promote);
> >-		notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
> >+
> >+		/* update fib in the rest of this address list */
> >+		ifa = promote;
> >+		while (ifa != NULL) {
> >+			notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
> >+			ifa = ifa->ifa_next;
> >+		}
> > 	}
> > }
> 
> You assume all addresses following the primary addresses are secondary
> addresses of the primary, which is not true with multiple primaries.
> This patch (untested) makes sure only to send notification for real
> secondaries of the deleted address.

Even this corrected version is only a workaround, the real bug is that 
or whatever reason all local routes of seconaries get deleted upon an
address promotion. I started debugging it a bit by looking at the
requests generated by fib_magic() and the resulting notifications, the
local routes just disappear when they shouldn't.

Situation is: 10.0.0.[1-4]/24 on dev0, 10.0.0.1 is the primary address
and gets deleted while address promotion is enabled. The following
happens:

	[Format:]
		Request generated by fib_magic()
			Notification event received

RTM_DELROUTE 10.0.0.0/24 dev eth0 scope link
  unicast table main protocol 2 preferred-src 10.0.0.1
        RTM_DELROUTE 10.0.0.0/24 dev eth0 scope link
          unicast table main protocol 2 preferred-src 10.0.0.1

RTM_DELROUTE 10.0.0.255 dev eth0 scope link
  broadcast table local protocol 2 preferred-src 10.0.0.1
        RTM_DELROUTE 10.0.0.255 dev eth0 scope link
          broadcast table local protocol 2 preferred-src 10.0.0.1

RTM_DELROUTE 10.0.0.0 dev eth0 scope link
  broadcast table local protocol 2 preferred-src 10.0.0.1
        RTM_DELROUTE 10.0.0.0 dev eth0 scope link
          broadcast table local protocol 2 preferred-src 10.0.0.1

RTM_DELROUTE 10.0.0.1 dev eth0 scope host
  local table local protocol 2 preferred-src 10.0.0.1
        RTM_DELROUTE 10.0.0.1 dev eth0 scope host
          local table local protocol 2 preferred-src 10.0.0.1

RTM_NEWROUTE 10.0.0.2 dev eth0 scope host
  local table local protocol 2 preferred-src 10.0.0.2
        RTM_NEWROUTE 10.0.0.2 dev eth0 scope host
          local table local protocol 2 preferred-src 10.0.0.2

RTM_NEWROUTE 10.0.0.0/24 dev eth0 scope link
  unicast table main protocol 2 preferred-src 10.0.0.2
        RTM_NEWROUTE 10.0.0.0/24 dev eth0 scope link
          unicast table main protocol 2 preferred-src 10.0.0.2

RTM_NEWROUTE 10.0.0.0 dev eth0 scope link
  broadcast table local protocol 2 preferred-src 10.0.0.2
        RTM_NEWROUTE 10.0.0.0 dev eth0 scope link
          broadcast table local protocol 2 preferred-src 10.0.0.2

RTM_NEWROUTE 10.0.0.255 dev eth0 scope link
  broadcast table local protocol 2 preferred-src 10.0.0.2
        RTM_NEWROUTE 10.0.0.255 dev eth0 scope link
          broadcast table local protocol 2 preferred-src 10.0.0.2

State afterwards:
4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
    inet 10.0.0.2/24 scope global eth0
    inet 10.0.0.3/24 scope global secondary eth0
    inet 10.0.0.4/24 scope global secondary eth0

broadcast 10.0.0.0  proto kernel  scope link  src 10.0.0.2 
local 10.0.0.2  proto kernel  scope host  src 10.0.0.2 
broadcast 10.0.0.255  proto kernel  scope link  src 10.0.0.2 

Local routes for 10.0.0.3 and 10.0.0.4 have disappeared _without_
any notification.

I think the correct way to fix this is to prevent the deletion of
the local routes, not just readding them. _If_ the deletion of them
is intended, which I doubt, then at least notifications must be
sent out.

Code to get fib_magic() requests to userspace:

Index: linux-2.6/include/linux/rtnetlink.h
===================================================================
--- linux-2.6.orig/include/linux/rtnetlink.h
+++ linux-2.6/include/linux/rtnetlink.h
@@ -880,6 +880,8 @@ enum rtnetlink_groups {
 #define RTNLGRP_DECnet_ROUTE	RTNLGRP_DECnet_ROUTE
 	RTNLGRP_IPV6_PREFIX,
 #define RTNLGRP_IPV6_PREFIX	RTNLGRP_IPV6_PREFIX
+	RTNLGRP_FIB_MAGIC,
+#define RTNLGRP_FIB_MAGIC	RTNLGRP_FIB_MAGIC
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
Index: linux-2.6/net/ipv4/fib_frontend.c
===================================================================
--- linux-2.6.orig/net/ipv4/fib_frontend.c
+++ linux-2.6/net/ipv4/fib_frontend.c
@@ -359,6 +359,48 @@ int inet_dump_fib(struct sk_buff *skb, s
 	return skb->len;
 }
 
+static int fib_magic_build(struct sk_buff *skb, int type, struct nlmsghdr *nlh,
+			   struct rtmsg *rtm, struct kern_rta *rta)
+{
+	struct nlmsghdr *dst = NULL;
+	struct rtmsg *rtm_dst;
+
+	dst = NLMSG_NEW(skb, current->pid, 0, type, sizeof(*rtm), 0);
+	memcpy(dst, nlh, sizeof(*nlh));
+
+	rtm_dst = NLMSG_DATA(dst);
+	memcpy(rtm_dst, rtm, sizeof(*rtm));
+	rtm_dst->rtm_family = AF_INET;
+
+	RTA_PUT(skb, RTA_DST, 4, rta->rta_dst);
+	RTA_PUT(skb, RTA_PREFSRC, 4, rta->rta_prefsrc);
+	RTA_PUT(skb, RTA_OIF, 4, rta->rta_oif);
+
+	return NLMSG_END(skb, dst);
+rtattr_failure:
+nlmsg_failure:
+	return NLMSG_CANCEL(skb, dst);
+}
+
+static void fib_magic_event(int type, struct nlmsghdr *nlh, struct rtmsg *rtm,
+			    struct kern_rta *rta)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(NLMSG_SPACE(sizeof(struct rtmsg) + 256), GFP_KERNEL);
+	if (!skb)
+		return;
+
+	if (fib_magic_build(skb, type, nlh, rtm, rta) < 0) {
+		kfree_skb(skb);
+		return;
+	}
+
+	NETLINK_CB(skb).dst_group = RTNLGRP_FIB_MAGIC;
+	netlink_broadcast(rtnl, skb, 0, RTNLGRP_FIB_MAGIC, GFP_KERNEL);
+}
+
+
 /* Prepare and feed intra-kernel routing request.
    Really, it should be netlink message, but :-( netlink
    can be not configured, so that we feed it directly
@@ -402,6 +444,8 @@ static void fib_magic(int cmd, int type,
 	rta.rta_prefsrc = &ifa->ifa_local;
 	rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
 
+	fib_magic_event(cmd, &req.nlh, &req.rtm, &rta);
+
 	if (cmd == RTM_NEWROUTE)
 		tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL);
 	else

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux