tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: RTM_NEWNEIGH
On 14/12/2014 22:23, David Young wrote:
> On Thu, Dec 11, 2014 at 12:57:58PM -0500, Greg Troxel wrote:
>>> dhcpcd polls SIOCGNBRINFO_IN6 every second for every IPv6 router it
>>> knows about to test neighbour reach-ability.
>>> This isn't exactly optimal, hello battery drain.
>>>
>>> Attached is a patch to add RTM_NEWNEIGH so that userland can react to
>>> Neighbour Discovery changes, similar to the Linux equivalent.
>>> It's designed to be protocol agnostic, (ie could be used for ARP as
>>> well).
>>> Currently, it only raises RTM_NEWNEIGH on IPv6 neighbour state and
>>> flag (is it a router?) changes.
>>> There is little point in generating RTM_DELNEIGH or RTM_GETNEIGH as
>>> Linux does because our current
>>> implementation sends equivalent messages via RTM_DELETE or RTM_CHANGE.
>>
>> Why doesn't RTM_ADD get sent for ND entries in the table? I don't see
>> why a new message is needed. Or is this about some later state
>> transition from them just being added, because the later transition is
>> what matters.
>
> I'd also like to know why RTM_ADD isn't sent for the new neighbors.
Because there is no code to notify userland!
Here is a new patch where all route changes are notified to userland:
* RTM_ADD for new neighbour cache entry
* RTM_CHANGE for an updated cache entry
* RTM_DEL for a deleted neighbour cache entry
Using this I can then detect host route additions/changes/deletions and
take action in dhcpcd accordingly. After all, I only care if I can reach
the router or not, I don't care about the neighbour state as such.
Would this patch be preferable? I'm guessing yes it would.
Comments welcome.
Roy
Index: netinet6/nd6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.c,v
retrieving revision 1.155
diff -u -p -r1.155 nd6.c
--- netinet6/nd6.c 3 Dec 2014 01:32:11 -0000 1.155
+++ netinet6/nd6.c 15 Dec 2014 17:59:54 -0000
@@ -1037,6 +1037,7 @@ nd6_free(struct rtentry *rt, int gc)
struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
struct in6_addr in6 = satocsin6(rt_getkey(rt))->sin6_addr;
struct nd_defrouter *dr;
+ struct rtentry *ort;
/*
* we used to have pfctlinput(PRC_HOSTDEAD) here.
@@ -1129,7 +1130,12 @@ nd6_free(struct rtentry *rt, int gc)
* caches, and disable the route entry not to be used in already
* cached routes.
*/
- rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0, NULL);
+ ort = NULL;
+ rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0, &ort);
+ if (ort) {
+ nd6_rtmsg(RTM_DELETE, rt); /* tell user process */
+ ort->rt_refcnt--;
+ }
return next;
}
@@ -2059,6 +2065,9 @@ fail:
break;
}
+ if (do_update)
+ nd6_rtmsg(RTM_CHANGE, rt); /* tell user process */
+
/*
* When the link-layer address of a router changes, select the
* best router again. In particular, when the neighbor entry is newly
Index: netinet6/nd6.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6.h,v
retrieving revision 1.60
diff -u -p -r1.60 nd6.h
--- netinet6/nd6.h 5 Sep 2014 06:08:15 -0000 1.60
+++ netinet6/nd6.h 15 Dec 2014 17:59:54 -0000
@@ -413,6 +413,7 @@ void nd6_option_init(void *, int, union
struct nd_opt_hdr *nd6_option(union nd_opts *);
int nd6_options(union nd_opts *);
struct rtentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *);
+void nd6_rtmsg(int, struct rtentry *);
void nd6_setmtu(struct ifnet *);
void nd6_llinfo_settimer(struct llinfo_nd6 *, long);
void nd6_timer(void *);
Index: netinet6/nd6_nbr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.102
diff -u -p -r1.102 nd6_nbr.c
--- netinet6/nd6_nbr.c 12 Oct 2014 20:05:50 -0000 1.102
+++ netinet6/nd6_nbr.c 15 Dec 2014 17:59:54 -0000
@@ -567,6 +567,7 @@ nd6_na_input(struct mbuf *m, int off, in
struct sockaddr_dl *sdl;
union nd_opts ndopts;
struct sockaddr_in6 ssin6;
+ int rtannounce;
if (ip6->ip6_hlim != 255) {
nd6log((LOG_ERR,
@@ -669,6 +670,7 @@ nd6_na_input(struct mbuf *m, int off, in
((sdl = satosdl(rt->rt_gateway)) == NULL))
goto freeit;
+ rtannounce = 0;
if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
/*
* If the link-layer has address, and no lladdr option came,
@@ -682,6 +684,7 @@ nd6_na_input(struct mbuf *m, int off, in
*/
(void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, lladdr,
ifp->if_addrlen);
+ rtannounce = 1;
if (is_solicited) {
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
@@ -712,11 +715,11 @@ nd6_na_input(struct mbuf *m, int off, in
else {
if (sdl->sdl_alen) {
if (memcmp(lladdr, CLLADDR(sdl), ifp->if_addrlen))
- llchange = 1;
+ llchange = rtannounce = 1;
else
llchange = 0;
} else
- llchange = 1;
+ llchange = rtannounce = 1;
}
/*
@@ -819,6 +822,8 @@ nd6_na_input(struct mbuf *m, int off, in
rt->rt_flags &= ~RTF_REJECT;
ln->ln_asked = 0;
nd6_llinfo_release_pkts(ln, ifp, rt);
+ if (rtannounce) /* tell user process about any new lladdr */
+ nd6_rtmsg(RTM_CHANGE, rt);
freeit:
m_freem(m);
Index: netinet6/nd6_rtr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.94
diff -u -p -r1.94 nd6_rtr.c
--- netinet6/nd6_rtr.c 5 Sep 2014 06:08:15 -0000 1.94
+++ netinet6/nd6_rtr.c 15 Dec 2014 17:59:54 -0000
@@ -76,7 +76,6 @@ static void pfxrtr_del(struct nd_pfxrout
static struct nd_pfxrouter *find_pfxlist_reachable_router
(struct nd_prefix *);
static void defrouter_delreq(struct nd_defrouter *);
-static void nd6_rtmsg(int, struct rtentry *);
static int in6_init_prefix_ltimes(struct nd_prefix *);
static void in6_init_address_ltimes(struct nd_prefix *,
@@ -416,7 +415,7 @@ nd6_ra_input(struct mbuf *m, int off, in
*/
/* tell the change to user processes watching the routing socket. */
-static void
+void
nd6_rtmsg(int cmd, struct rtentry *rt)
{
struct rt_addrinfo info;
Home |
Main Index |
Thread Index |
Old Index