Date: Mon, 1 Jul 2013 12:58:23 -0700 From: Loganaden Velvindron <logan@elandsys.com> To: freebsd-net@freebsd.org Cc: bz@freebsd.org Subject: kern/157410: [ip6] IPv6 Router Advertisements Cause Excessive CPU Use Message-ID: <20130701195823.GA207@mx.elandsys.com>
next in thread | raw e-mail | index | archive | help
Hi I came across this old PR. It appears that it's not fixed in -current. I attempted to port the diff to our FreeBSD 9.1 release machines which have IPv6 connectivity and are affected by RA flooding. I can report that it mitigates RA_flooding. Feedback welcomed. I'd be happy to polish it so that it can make it to 9.2 and 10.0 :-) I broke down the diffs into separate ones. --- in6.c.orig 2013-06-30 23:07:46.000000000 +0400 +++ in6.c 2013-07-01 19:20:15.000000000 +0400 @@ -2694,6 +2694,8 @@ in6_domifattach(struct ifnet *ifp) ext->nd_ifinfo = nd6_ifattach(ifp); ext->scope6_id = scope6_ifattach(ifp); ext->lltable = lltable_init(ifp, AF_INET6); + ext->nprefixes = 0; + ext->ndefrouters = 0; if (ext->lltable != NULL) { ext->lltable->llt_free = in6_lltable_free; ext->lltable->llt_prefix_free = in6_lltable_prefix_free; --- in6_proto.c.orig 2013-06-30 23:07:58.000000000 +0400 +++ in6_proto.c 2013-07-01 21:05:08.000000000 +0400 @@ -413,7 +413,8 @@ VNET_DEFINE(int, ip6_rr_prune) = 5; /* r * walk list every 5 sec. */ VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */ VNET_DEFINE(int, ip6_v6only) = 1; - +VNET_DEFINE(int, ip6_maxifprefixes) = 16; +VNET_DEFINE(int, ip6_maxifdefrouters) = 16; VNET_DEFINE(int, ip6_keepfaith) = 0; VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L; #ifdef IPSTEALTH @@ -524,6 +525,10 @@ SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6C &VNET_NAME(ip6stat), ip6stat, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets, CTLFLAG_RW, &VNET_NAME(ip6_maxfragpackets), 0, ""); +SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXIFPREFIXES, maxifprefixes, + CTLFLAG_RW, &VNET_NAME(ip6_maxifprefixes), 0, ""); +SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXIFDEFROUTERS, maxifdefrouters, + CTLFLAG_RW, &VNET_NAME(ip6_maxifdefrouters), 0, ""); SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV, accept_rtadv, CTLFLAG_RW, &VNET_NAME(ip6_accept_rtadv), 0, "Default value of per-interface flag for accepting ICMPv6 Router" --- in6_var.h.orig 2013-06-30 23:08:28.000000000 +0400 +++ in6_var.h 2013-07-01 22:38:03.000000000 +0400 @@ -104,6 +104,8 @@ struct in6_ifextra { struct scope6_id *scope6_id; struct lltable *lltable; struct mld_ifinfo *mld_ifinfo; + int nprefixes; + int ndefrouters; }; #define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable) --- ip6_var.h.orig 2013-06-30 23:09:22.000000000 +0400 +++ ip6_var.h 2013-07-01 20:28:30.000000000 +0400 @@ -315,6 +315,8 @@ VNET_DECLARE(int, ip6_maxfragpackets); / * queue */ VNET_DECLARE(int, ip6_maxfrags); /* Maximum fragments in reassembly * queue */ +VNET_DECLARE(int, ip6_maxifprefixes); +VNET_DECLARE(int, ip6_maxifdefrouters); VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */ VNET_DECLARE(int, ip6_no_radr); /* No defroute from RA */ VNET_DECLARE(int, ip6_norbit_raif); /* Disable R-bit in NA on RA --- nd6.h.orig 2013-06-30 23:09:42.000000000 +0400 +++ nd6.h 2013-07-01 22:16:09.000000000 +0400 @@ -277,6 +277,7 @@ struct nd_prefix { u_char ndpr_plen; int ndpr_refcnt; /* reference couter from addresses */ }; +#define ndpr_next ndpr_entry.le_next #define ndpr_raf ndpr_flags #define ndpr_raf_onlink ndpr_flags.onlink --- nd6_rtr.c.orig 2013-06-30 23:10:24.000000000 +0400 +++ nd6_rtr.c 2013-07-01 22:40:29.000000000 +0400 @@ -83,6 +83,7 @@ static void nd6_rtmsg(int, struct rtentr static int in6_init_prefix_ltimes(struct nd_prefix *); static void in6_init_address_ltimes __P((struct nd_prefix *, struct in6_addrlifetime *)); +static void purge_detached(struct ifnet *); static int nd6_prefix_onlink(struct nd_prefix *); static int nd6_prefix_offlink(struct nd_prefix *); @@ -565,6 +566,7 @@ defrtrlist_del(struct nd_defrouter *dr) { struct nd_defrouter *deldr = NULL; struct nd_prefix *pr; + struct in6_ifextra *ext = dr->ifp->if_afdata[AF_INET6]; /* * Flush all the routing table entries that use the router @@ -597,6 +599,12 @@ defrtrlist_del(struct nd_defrouter *dr) if (deldr) defrouter_select(); + ext->ndefrouters--; + if (ext->ndefrouters < 0) { + log(LOG_WARNING, "defrtrlist_del: negative count on %s\n", + dr->ifp->if_xname); + } + free(dr, M_IP6NDP); } @@ -734,6 +742,7 @@ static struct nd_defrouter * defrtrlist_update(struct nd_defrouter *new) { struct nd_defrouter *dr, *n; + struct in6_ifextra *ext = new->ifp->if_afdata[AF_INET6]; int s = splnet(); if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) { @@ -775,6 +784,12 @@ defrtrlist_update(struct nd_defrouter *n splx(s); return (dr); } + /*struct in6_ifextra *ext = new->ifp->if_afdata[AF_INET6];*/ + if (ip6_maxifdefrouters >= 0 && + ext->ndefrouters >= ip6_maxifdefrouters) { + splx(s); + return (NULL); + } /* entry does not exist */ if (new->rtlifetime == 0) { @@ -810,6 +825,8 @@ insert: defrouter_select();
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130701195823.GA207>