All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Schroeder <mls@suse.de>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] new "fromarp" route flag
Date: Mon, 22 Mar 2004 18:25:51 +0100	[thread overview]
Message-ID: <20040322172551.GC8210@suse.de> (raw)


The following patch implements a new route flag, "fromarp".

Problem description:
--------------------

Zeroconf hardware automatically assigns an ip address from the
link local range (169.254.1.0 - 169.254.254.255). This ip addresses
don't get routed and are local to the interfaces. To address such
a component, one can add a link local route:

    ip route add 169.254.0.0/16 dev eth0

Things get ugly if a host is multihomed and zeroconf hardware is
conected to more than one interface. It is not possible to add
a route in that case.

Solution:
---------

My patch adds a new route flag, "fromarp", to the kernel. Example:

    ip route add 169.254.0.0/16 fromarp nexthop dev eth0 nexthop dev eth1

If a packet is to be send with such a route, the kernel
checks the arp cache of the interfaces specified in the route.
If a match is found, the packet is send to the matching interface.
Otherwise an arp request is sent from all of the interfaces.

Comments anyone?

--- ./include/linux/in_route.h.orig	2004-03-19 11:20:12.000000000 +0000
+++ ./include/linux/in_route.h	2004-03-19 11:21:18.000000000 +0000
@@ -18,6 +18,7 @@
 #define RTCF_MASQ	0x00400000
 #define RTCF_SNAT	0x00800000
 #define RTCF_DOREDIRECT 0x01000000
+#define RTCF_FROMARP    0x02000000
 #define RTCF_DIRECTSRC	0x04000000
 #define RTCF_DNAT	0x08000000
 #define RTCF_BROADCAST	0x10000000
--- ./include/linux/rtnetlink.h.orig	2004-03-19 11:20:12.000000000 +0000
+++ ./include/linux/rtnetlink.h	2004-03-19 11:21:18.000000000 +0000
@@ -170,6 +170,7 @@
 #define RTM_F_CLONED		0x200	/* This route is cloned		*/
 #define RTM_F_EQUALIZE		0x400	/* Multipath equalizer: NI	*/
 #define RTM_F_PREFIX		0x800	/* Prefix addresses		*/
+#define RTM_F_FROMARP		0x1000	/* Select if from arpcache      */
 
 /* Reserved table identifiers */
 
--- ./net/ipv4/arp.c.orig	2004-03-19 11:19:43.000000000 +0000
+++ ./net/ipv4/arp.c	2004-03-19 11:21:18.000000000 +0000
@@ -952,6 +952,12 @@
 	return 0;
 }
 
+struct neighbour *arp_lookup(u32 ip, struct net_device *dev, int creat)
+{
+        return __neigh_lookup(&arp_tbl, &ip, dev, creat);
+}
+
+
 /*
  *	User level interface (ioctl)
  */
--- ./net/ipv4/fib_semantics.c.orig	2004-03-19 11:20:18.000000000 +0000
+++ ./net/ipv4/fib_semantics.c	2004-03-19 11:21:18.000000000 +0000
@@ -1035,4 +1035,52 @@
 	res->nh_sel = 0;
 	spin_unlock_bh(&fib_multipath_lock);
 }
+
+extern struct neighbour *arp_lookup(u32 ip, struct net_device *dev, int creat);
+
+int fib_select_fromarp(const struct flowi *flp, struct fib_result *res)
+{
+	struct net_device *dev;
+	struct fib_info *fi = res->fi;
+	struct neighbour *n;
+	u32 ip;
+	int i, new;
+
+	res->nh_sel = 0;
+	ip = flp->nl_u.ip4_u.daddr;
+	if (ip == 0xffffffff || MULTICAST(ip))
+		return 1;
+	spin_lock_bh(&fib_multipath_lock);
+	for (i = 0, new = -1; i < fi->fib_nhs; i++) {
+		dev = fi->fib_nh[i].nh_dev;
+		n = arp_lookup(ip, dev, 0);
+		if (!n) {
+			if (new < 0)
+				new = i;
+			continue;
+		}
+		if ((n->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)) != 0) {
+			res->nh_sel = i;
+			neigh_release(n);
+			spin_unlock_bh(&fib_multipath_lock);
+			return 1;
+		}
+		neigh_release(n);
+	}
+	if (new < 0)
+		new = 0;
+	res->nh_sel = new;
+	for (i = 0; i < fi->fib_nhs; i++) {
+		if (i == new)
+			continue;
+		dev = fi->fib_nh[i].nh_dev;
+		if ((n = arp_lookup(ip, dev, 1)) != 0) {
+			neigh_event_send(n, (struct sk_buff *)0);
+			neigh_release(n);
+		}
+	}
+	spin_unlock_bh(&fib_multipath_lock);
+	return 0;
+}
+
 #endif
--- ./net/ipv4/route.c.orig	2004-03-19 11:20:18.000000000 +0000
+++ ./net/ipv4/route.c	2004-03-19 11:21:18.000000000 +0000
@@ -1332,7 +1332,9 @@
 {
 	struct rtable *rt;
 
-	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+	rt = (struct rtable *) skb->dst;
+	if (!rt || !(rt->rt_flags & RTCF_FROMARP))
+		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
 
 	rt = (struct rtable *) skb->dst;
 	if (rt)
@@ -2077,9 +2079,13 @@
 	}
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res.fi->fib_nhs > 1 && fl.oif == 0)
-		fib_select_multipath(&fl, &res);
-	else
+	if (res.fi->fib_nhs > 1 && fl.oif == 0) {
+		if (res.fi->fib_flags & RTM_F_FROMARP) {
+			if (!fib_select_fromarp(&fl, &res))
+				flags |= RTCF_FROMARP;
+		} else
+			fib_select_multipath(&fl, &res);
+	}
 #endif
 	if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
 		fib_select_default(&fl, &res);
@@ -2190,8 +2196,18 @@
 
 	rth->rt_flags = flags;
 
-	hash = rt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos);
-	err = rt_intern_hash(hash, rth, rp);
+	if (flags & RTCF_FROMARP) {
+		err = 0;
+		if (rth->rt_type == RTN_UNICAST || rth->fl.iif == 0) {
+			if ((err = arp_bind_neighbour(&rth->u.dst)) != 0)
+				rt_drop(rth);
+		}
+		if (!err)
+			*rp = rth;
+	} else {
+		hash = rt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos);
+		err = rt_intern_hash(hash, rth, rp);
+	}
 done:
 	if (free_res)
 		fib_res_put(&res);


Cheers,
  Michael.

-- 
Michael Schroeder                                   mls@suse.de
main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}

             reply	other threads:[~2004-03-22 17:26 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-22 17:25 Michael Schroeder [this message]
  -- strict thread matches above, loose matches on Subject: below --
2004-03-22 17:27 [PATCH] new "fromarp" route flag Michael Schroeder

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040322172551.GC8210@suse.de \
    --to=mls@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.