summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2008-12-15 06:10:57 +0000
committerqingli <qingli@FreeBSD.org>2008-12-15 06:10:57 +0000
commitec826ad5c7f97de814529d3b3bae7950f91d9a5d (patch)
tree281ff6a89cacadf7e72f506b037ca41229a23bf6 /sys/net
parent664c3aeb0118ccccb068f485e30353a47923b4d0 (diff)
downloadFreeBSD-src-ec826ad5c7f97de814529d3b3bae7950f91d9a5d.zip
FreeBSD-src-ec826ad5c7f97de814529d3b3bae7950f91d9a5d.tar.gz
This main goals of this project are:
1. separating L2 tables (ARP, NDP) from the L3 routing tables 2. removing as much locking dependencies among these layers as possible to allow for some parallelism in the search operations 3. simplify the logic in the routing code, The most notable end result is the obsolescent of the route cloning (RTF_CLONING) concept, which translated into code reduction in both IPv4 ARP and IPv6 NDP related modules, and size reduction in struct rtentry{}. The change in design obsoletes the semantics of RTF_CLONING, RTF_WASCLONE and RTF_LLINFO routing flags. The userland applications such as "arp" and "ndp" have been modified to reflect those changes. The output from "netstat -r" shows only the routing entries. Quite a few developers have contributed to this project in the past: Glebius Smirnoff, Luigi Rizzo, Alessandro Cerri, and Andre Oppermann. And most recently: - Kip Macy revised the locking code completely, thus completing the last piece of the puzzle, Kip has also been conducting active functional testing - Sam Leffler has helped me improving/refactoring the code, and provided valuable reviews - Julian Elischer setup the perforce tree for me and has helped me maintaining that branch before the svn conversion
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c4
-rw-r--r--sys/net/if_arcsubr.c6
-rw-r--r--sys/net/if_atmsubr.c13
-rw-r--r--sys/net/if_ethersubr.c19
-rw-r--r--sys/net/if_fddisubr.c6
-rw-r--r--sys/net/if_fwsubr.c16
-rw-r--r--sys/net/if_iso88025subr.c15
-rw-r--r--sys/net/if_var.h6
-rw-r--r--sys/net/radix_mpath.c4
-rw-r--r--sys/net/route.c602
-rw-r--r--sys/net/route.h19
-rw-r--r--sys/net/rtsock.c40
12 files changed, 134 insertions, 616 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 5142a5c..6f829b7 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -60,6 +60,7 @@
#include <sys/jail.h>
#include <sys/vimage.h>
#include <machine/stdarg.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -1366,6 +1367,9 @@ done:
return (ifa);
}
+#include <net/route.h>
+#include <net/if_llatbl.h>
+
/*
* Default action when installing a route with a Link Level gateway.
* Lookup an appropriate real ifa to point to.
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c
index 0f5fef3..023b647 100644
--- a/sys/net/if_arcsubr.c
+++ b/sys/net/if_arcsubr.c
@@ -64,6 +64,7 @@
#include <net/if_arc.h>
#include <net/if_arp.h>
#include <net/bpf.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -108,6 +109,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
u_int8_t atype, adst;
int loop_copy = 0;
int isphds;
+ struct llentry *lle;
if (!((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
@@ -127,7 +129,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
else if (ifp->if_flags & IFF_NOARP)
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
else {
- error = arpresolve(ifp, rt0, m, dst, &adst);
+ error = arpresolve(ifp, rt0, m, dst, &adst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -165,7 +167,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst, &lle);
if (error)
return (error);
atype = ARCTYPE_INET6;
diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c
index 9d1a7fa..7e36187 100644
--- a/sys/net/if_atmsubr.c
+++ b/sys/net/if_atmsubr.c
@@ -153,22 +153,11 @@ atm_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
case AF_INET:
case AF_INET6:
{
- struct rtentry *rt = NULL;
- /*
- * check route
- */
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
-
if (dst->sa_family == AF_INET6)
etype = ETHERTYPE_IPV6;
else
etype = ETHERTYPE_IP;
- if (!atmresolve(rt, m, dst, &atmdst)) {
+ if (!atmresolve(rt0, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
senderr(EHOSTUNREACH);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 4524fdd..e5978c6 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -64,6 +64,7 @@
#include <net/ethernet.h>
#include <net/if_bridgevar.h>
#include <net/if_vlan_var.h>
+#include <net/if_llatbl.h>
#include <net/pf_mtag.h>
#include <net/vnet.h>
@@ -87,6 +88,7 @@
#include <netipx/ipx.h>
#include <netipx/ipx_if.h>
#endif
+
int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
struct sockaddr *dst, short *tp, int *hlen);
@@ -151,6 +153,7 @@ static int ether_ipfw;
#endif
#endif
+
/*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
@@ -164,6 +167,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
short type;
int error, hdrcmplt = 0;
u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
+ struct llentry *lle = NULL;
struct ether_header *eh;
struct pf_mtag *t;
int loop_copy = 1;
@@ -186,7 +190,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -221,7 +225,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle);
if (error)
return error;
type = htons(ETHERTYPE_IPV6);
@@ -289,6 +293,17 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
senderr(EAFNOSUPPORT);
}
+ if (lle != NULL && (lle->la_flags & LLE_IFADDR)) {
+ int csum_flags = 0;
+ if (m->m_pkthdr.csum_flags & CSUM_IP)
+ csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
+ csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
+ m->m_pkthdr.csum_flags |= csum_flags;
+ m->m_pkthdr.csum_data = 0xffff;
+ return (if_simloop(ifp, m, dst->sa_family, 0));
+ }
+
/*
* Add local net header. If no space in first mbuf,
* allocate another.
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index e37d7ae..26d64e0 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -55,6 +55,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/ethernet.h>
#include <net/netisr.h>
@@ -120,6 +121,7 @@ fddi_output(ifp, m, dst, rt0)
int loop_copy = 0, error = 0, hdrcmplt = 0;
u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
struct fddi_header *fh;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -137,7 +139,7 @@ fddi_output(ifp, m, dst, rt0)
switch (dst->sa_family) {
#ifdef INET
case AF_INET: {
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -173,7 +175,7 @@ fddi_output(ifp, m, dst, rt0)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle);
if (error)
return (error); /* Something bad happened */
type = htons(ETHERTYPE_IPV6);
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
index 77e7b70..b087370 100644
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -51,6 +51,7 @@
#include <net/if_types.h>
#include <net/bpf.h>
#include <net/firewire.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -80,7 +81,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
{
struct fw_com *fc = IFP2FWC(ifp);
int error, type;
- struct rtentry *rt = NULL;
struct m_tag *mtag;
union fw_encap *enc;
struct fw_hwaddr *destfw;
@@ -89,6 +89,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct mbuf *mtail;
int unicast, dgl, foff;
static int next_dgl;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -102,13 +103,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
goto bad;
}
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
-
/*
* For unicast, we make a tag to store the lladdr of the
* destination. This might not be the first time we have seen
@@ -144,7 +138,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
* doesn't fit into the arp model.
*/
if (unicast) {
- error = arpresolve(ifp, rt, m, dst, (u_char *) destfw);
+ error = arpresolve(ifp, rt0, m, dst, (u_char *) destfw, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -173,8 +167,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#ifdef INET6
case AF_INET6:
if (unicast) {
- error = nd6_storelladdr(fc->fc_ifp, rt, m, dst,
- (u_char *) destfw);
+ error = nd6_storelladdr(fc->fc_ifp, rt0, m, dst,
+ (u_char *) destfw, &lle);
if (error)
return (error);
}
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index 00e323a..2bc336c 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -59,6 +59,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/ethernet.h>
#include <net/netisr.h>
@@ -243,7 +244,7 @@ iso88025_output(ifp, m, dst, rt0)
struct iso88025_header *th;
struct iso88025_header gen_th;
struct sockaddr_dl *sdl = NULL;
- struct rtentry *rt = NULL;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -260,14 +261,8 @@ iso88025_output(ifp, m, dst, rt0)
/* Calculate routing info length based on arp table entry */
/* XXX any better way to do this ? */
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
- if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway))
+ if (rt0 && (sdl = (struct sockaddr_dl *)rt0->rt_gateway))
if (SDL_ISO88025(sdl)->trld_rcf != 0)
rif_len = TR_RCF_RIFLEN(SDL_ISO88025(sdl)->trld_rcf);
@@ -289,7 +284,7 @@ iso88025_output(ifp, m, dst, rt0)
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IP;
@@ -324,7 +319,7 @@ iso88025_output(ifp, m, dst, rt0)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle);
if (error)
return (error);
snap_type = ETHERTYPE_IPV6;
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 62c2b99..c4cb4f6 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -169,8 +169,6 @@ struct ifnet {
void *if_bridge; /* bridge glue */
- struct lltable *lltables; /* list of L3-L2 resolution tables */
-
struct label *if_label; /* interface MAC label */
/* these are only used by IPv6 */
@@ -181,6 +179,7 @@ struct ifnet {
struct task if_starttask; /* task for IFF_NEEDSGIANT */
struct task if_linktask; /* task for link change events */
struct mtx if_addr_mtx; /* mutex to protect address lists */
+
LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
/* protected by if_addr_mtx */
@@ -365,6 +364,9 @@ EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
#define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx)
#define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_mtx)
+#define IF_AFDATA_LOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_mtx, MA_OWNED)
+#define IF_AFDATA_UNLOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_mtx, MA_NOTOWNED)
+
#define IFF_LOCKGIANT(ifp) do { \
if ((ifp)->if_flags & IFF_NEEDSGIANT) \
mtx_lock(&Giant); \
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c
index 68233fe..8d94d01 100644
--- a/sys/net/radix_mpath.c
+++ b/sys/net/radix_mpath.c
@@ -266,8 +266,8 @@ rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum)
* be done for sendto(3) case?
*/
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
- return; /* XXX */
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, RTF_CLONING, fibnum);
+ return;
+ ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);
/* if the route does not exist or it is not multipath, don't care */
if (ro->ro_rt == NULL)
diff --git a/sys/net/route.c b/sys/net/route.c
index be71e13..9359514 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
@@ -53,6 +54,7 @@
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/route.h>
#ifdef RADIX_MPATH
@@ -269,8 +271,7 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
struct radix_node *rn;
struct rtentry *newrt;
struct rt_addrinfo info;
- u_long nflags;
- int needresolve = 0, err = 0, msgtype = RTM_MISS;
+ int err = 0, msgtype = RTM_MISS;
int needlock;
KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
@@ -283,10 +284,9 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
*/
if (rnh == NULL) {
V_rtstat.rts_unreach++;
- goto miss2;
+ goto miss;
}
needlock = !(ignflags & RTF_RNH_LOCKED);
-retry:
if (needlock)
RADIX_NODE_HEAD_RLOCK(rnh);
#ifdef INVARIANTS
@@ -295,103 +295,33 @@ retry:
#endif
rn = rnh->rnh_matchaddr(dst, rnh);
if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
-
newrt = rt = RNTORT(rn);
- nflags = rt->rt_flags & ~ignflags;
- if (report && (nflags & RTF_CLONING)) {
- if (needlock && !RADIX_NODE_HEAD_LOCK_TRY_UPGRADE(rnh)) {
- RADIX_NODE_HEAD_RUNLOCK(rnh);
- RADIX_NODE_HEAD_LOCK(rnh);
- /*
- * lookup again to make sure it wasn't changed
- */
- rn = rnh->rnh_matchaddr(dst, rnh);
- if (!(rn && ((rn->rn_flags & RNF_ROOT) == 0))) {
- RADIX_NODE_HEAD_UNLOCK(rnh);
- needresolve = 0;
- log(LOG_INFO, "retrying route lookup ...\n");
- goto retry;
- }
- }
- needresolve = 1;
- } else {
- RT_LOCK(newrt);
- RT_ADDREF(newrt);
- if (needlock)
- RADIX_NODE_HEAD_RUNLOCK(rnh);
- goto done;
- }
- }
+ RT_LOCK(newrt);
+ RT_ADDREF(newrt);
+ if (needlock)
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ goto done;
+
+ } else if (needlock)
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+
/*
- * if needresolve is set then we have the exclusive lock
- * and we need to keep it held for the benefit of rtrequest_fib
+ * Either we hit the root or couldn't find any match,
+ * Which basically means
+ * "caint get there frm here"
*/
- if (!needresolve && needlock)
- RADIX_NODE_HEAD_RUNLOCK(rnh);
-
- if (needresolve) {
- RADIX_NODE_HEAD_WLOCK_ASSERT(rnh);
+ V_rtstat.rts_unreach++;
+miss:
+ if (report) {
/*
- * We are apparently adding (report = 0 in delete).
- * If it requires that it be cloned, do so.
- * (This implies it wasn't a HOST route.)
+ * If required, report the failure to the supervising
+ * Authorities.
+ * For a delete, this is not an error. (report == 0)
*/
- err = rtrequest_fib(RTM_RESOLVE, dst, NULL,
- NULL, RTF_RNH_LOCKED, &newrt, fibnum);
- if (err) {
- /*
- * If the cloning didn't succeed, maybe
- * what we have will do. Return that.
- */
- newrt = rt; /* existing route */
- RT_LOCK(newrt);
- RT_ADDREF(newrt);
- goto miss;
- }
- KASSERT(newrt, ("no route and no error"));
- RT_LOCK(newrt);
- if (newrt->rt_flags & RTF_XRESOLVE) {
- /*
- * If the new route specifies it be
- * externally resolved, then go do that.
- */
- msgtype = RTM_RESOLVE;
- goto miss;
- }
- /* Inform listeners of the new route. */
bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = rt_key(newrt);
- info.rti_info[RTAX_NETMASK] = rt_mask(newrt);
- info.rti_info[RTAX_GATEWAY] = newrt->rt_gateway;
- if (newrt->rt_ifp != NULL) {
- info.rti_info[RTAX_IFP] =
- newrt->rt_ifp->if_addr->ifa_addr;
- info.rti_info[RTAX_IFA] = newrt->rt_ifa->ifa_addr;
- }
- rt_missmsg(RTM_ADD, &info, newrt->rt_flags, 0);
- if (needlock)
- RADIX_NODE_HEAD_UNLOCK(rnh);
- } else {
- /*
- * Either we hit the root or couldn't find any match,
- * Which basically means
- * "caint get there frm here"
- */
- V_rtstat.rts_unreach++;
- miss:
- if (needlock && needresolve)
- RADIX_NODE_HEAD_UNLOCK(rnh);
- miss2: if (report) {
- /*
- * If required, report the failure to the supervising
- * Authorities.
- * For a delete, this is not an error. (report == 0)
- */
- bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = dst;
- rt_missmsg(msgtype, &info, 0, err);
- }
- }
+ info.rti_info[RTAX_DST] = dst;
+ rt_missmsg(msgtype, &info, 0, err);
+ }
done:
if (newrt)
RT_LOCK_ASSERT(newrt);
@@ -420,7 +350,7 @@ rtfree(struct rtentry *rt)
*/
RT_REMREF(rt);
if (rt->rt_refcnt > 0) {
- printf("%s: %p has %lu refs\n", __func__, rt, rt->rt_refcnt);
+ log(LOG_DEBUG, "%s: %p has %d refs\t", __func__, rt, rt->rt_refcnt);
goto done;
}
@@ -461,8 +391,6 @@ rtfree(struct rtentry *rt)
*/
if (rt->rt_ifa)
IFAFREE(rt->rt_ifa);
- rt->rt_parent = NULL; /* NB: no refcnt on parent */
-
/*
* The key is separatly alloc'd so free it (see rt_setgate()).
* This also frees the gateway, as they are always malloc'd
@@ -715,14 +643,6 @@ ifa_ifwithroute_fib(int flags, struct sockaddr *dst, struct sockaddr *gateway,
return (ifa);
}
-static walktree_f_t rt_fixdelete;
-static walktree_f_t rt_fixchange;
-
-struct rtfc_arg {
- struct rtentry *rt0;
- struct radix_node_head *rnh;
-};
-
/*
* Do appropriate manipulations of a routing tree given
* all the bits of info needed
@@ -828,8 +748,13 @@ rtexpunge(struct rtentry *rt)
struct ifaddr *ifa;
int error = 0;
+ /*
+ * Find the correct routing tree to use for this Address Family
+ */
rnh = V_rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family];
RT_LOCK_ASSERT(rt);
+ if (rnh == NULL)
+ return (EAFNOSUPPORT);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
#if 0
/*
@@ -840,13 +765,6 @@ rtexpunge(struct rtentry *rt)
KASSERT(rt->rt_refcnt <= 1, ("bogus refcnt %ld", rt->rt_refcnt));
#endif
/*
- * Find the correct routing tree to use for this Address Family
- */
- rnh = V_rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family];
- if (rnh == NULL)
- return (EAFNOSUPPORT);
-
- /*
* Remove the item from the tree; it should be there,
* but when callers invoke us blindly it may not (sigh).
*/
@@ -863,24 +781,6 @@ rtexpunge(struct rtentry *rt)
rt->rt_flags &= ~RTF_UP;
/*
- * Now search what's left of the subtree for any cloned
- * routes which might have been formed from this node.
- */
- if ((rt->rt_flags & RTF_CLONING) && rt_mask(rt))
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixdelete, rt);
-
- /*
- * Remove any external references we may have.
- * This might result in another rtentry being freed if
- * we held its last reference.
- */
- if (rt->rt_gwroute) {
- RTFREE(rt->rt_gwroute);
- rt->rt_gwroute = NULL;
- }
-
- /*
* Give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) {
@@ -904,12 +804,6 @@ bad:
}
int
-rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
-{
- return (rtrequest1_fib(req, info, ret_nrt, 0));
-}
-
-int
rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
u_int fibnum)
{
@@ -941,10 +835,9 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
* If we are adding a host route then we don't want to put
* a netmask in the tree, nor do we want to clone it.
*/
- if (flags & RTF_HOST) {
+ if (flags & RTF_HOST)
netmask = NULL;
- flags &= ~RTF_CLONING;
- }
+
switch (req) {
case RTM_DELETE:
#ifdef RADIX_MPATH
@@ -1023,26 +916,6 @@ normal_rtdel:
rt->rt_flags &= ~RTF_UP;
/*
- * Now search what's left of the subtree for any cloned
- * routes which might have been formed from this node.
- */
- if ((rt->rt_flags & RTF_CLONING) &&
- rt_mask(rt)) {
- rnh->rnh_walktree_from(rnh, dst, rt_mask(rt),
- rt_fixdelete, rt);
- }
-
- /*
- * Remove any external references we may have.
- * This might result in another rtentry being freed if
- * we held its last reference.
- */
- if (rt->rt_gwroute) {
- RTFREE(rt->rt_gwroute);
- rt->rt_gwroute = NULL;
- }
-
- /*
* give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
@@ -1069,20 +942,12 @@ deldone:
} else
RTFREE_LOCKED(rt);
break;
-
case RTM_RESOLVE:
- if (ret_nrt == NULL || (rt = *ret_nrt) == NULL)
- senderr(EINVAL);
- ifa = rt->rt_ifa;
- /* XXX locking? */
- flags = rt->rt_flags &
- ~(RTF_CLONING | RTF_STATIC);
- flags |= RTF_WASCLONED;
- gateway = rt->rt_gateway;
- if ((netmask = rt->rt_genmask) == NULL)
- flags |= RTF_HOST;
- goto makeroute;
-
+ /*
+ * resolve was only used for route cloning
+ * here for compat
+ */
+ break;
case RTM_ADD:
if ((flags & RTF_GATEWAY) && !gateway)
senderr(EINVAL);
@@ -1093,8 +958,6 @@ deldone:
if (info->rti_ifa == NULL && (error = rt_getifa_fib(info, fibnum)))
senderr(error);
ifa = info->rti_ifa;
-
- makeroute:
rt = uma_zalloc(rtzone, M_NOWAIT | M_ZERO);
if (rt == NULL)
senderr(ENOBUFS);
@@ -1103,7 +966,7 @@ deldone:
rt->rt_fibnum = fibnum;
/*
* Add the gateway. Possibly re-malloc-ing the storage for it
- * also add the rt_gwroute if possible.
+ *
*/
RT_LOCK(rt);
if ((error = rt_setgate(rt, dst, gateway)) != 0) {
@@ -1138,8 +1001,6 @@ deldone:
/* do not permit exactly the same dst/mask/gw pair */
if (rn_mpath_capable(rnh) &&
rt_mpath_conflict(rnh, rt, netmask)) {
- if (rt->rt_gwroute)
- RTFREE(rt->rt_gwroute);
if (rt->rt_ifa) {
IFAFREE(rt->rt_ifa);
}
@@ -1152,34 +1013,11 @@ deldone:
/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
- if (rn == NULL) {
- struct rtentry *rt2;
- /*
- * Uh-oh, we already have one of these in the tree.
- * We do a special hack: if the route that's already
- * there was generated by the cloning mechanism
- * then we just blow it away and retry the insertion
- * of the new one.
- */
- rt2 = rtalloc1_fib(dst, 0, RTF_RNH_LOCKED, fibnum);
- if (rt2 && rt2->rt_parent) {
- rtexpunge(rt2);
- RT_UNLOCK(rt2);
- rn = rnh->rnh_addaddr(ndst, netmask,
- rnh, rt->rt_nodes);
- } else if (rt2) {
- /* undo the extra ref we got */
- RTFREE_LOCKED(rt2);
- }
- }
-
/*
* If it still failed to go into the tree,
* then un-make it (this should be a function)
*/
if (rn == NULL) {
- if (rt->rt_gwroute)
- RTFREE(rt->rt_gwroute);
if (rt->rt_ifa)
IFAFREE(rt->rt_ifa);
Free(rt_key(rt));
@@ -1188,33 +1026,6 @@ deldone:
senderr(EEXIST);
}
- rt->rt_parent = NULL;
-
- /*
- * If we got here from RESOLVE, then we are cloning
- * so clone the rest, and note that we
- * are a clone (and increment the parent's references)
- */
- if (req == RTM_RESOLVE) {
- KASSERT(ret_nrt && *ret_nrt,
- ("no route to clone from"));
- rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
- rt->rt_rmx.rmx_pksent = 0; /* reset packet counter */
- if ((*ret_nrt)->rt_flags & RTF_CLONING) {
- /*
- * NB: We do not bump the refcnt on the parent
- * entry under the assumption that it will
- * remain so long as we do. This is
- * important when deleting the parent route
- * as this operation requires traversing
- * the tree to delete all clones and futzing
- * with refcnts requires us to double-lock
- * parent through this back reference.
- */
- rt->rt_parent = *ret_nrt;
- }
- }
-
/*
* If this protocol has something to add to this then
* allow it to do that as well.
@@ -1223,20 +1034,6 @@ deldone:
ifa->ifa_rtrequest(req, rt, info);
/*
- * We repeat the same procedure from rt_setgate() here because
- * it doesn't fire when we call it there because the node
- * hasn't been added to the tree yet.
- */
- if (req == RTM_ADD &&
- !(rt->rt_flags & RTF_HOST) && rt_mask(rt) != NULL) {
- struct rtfc_arg arg;
- arg.rnh = rnh;
- arg.rt0 = rt;
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixchange, &arg);
- }
-
- /*
* actually return a resultant rtentry and
* give the caller a single reference.
*/
@@ -1263,159 +1060,21 @@ bad:
#undef ifpaddr
#undef flags
-/*
- * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
- * (i.e., the routes related to it by the operation of cloning). This
- * routine is iterated over all potential former-child-routes by way of
- * rnh->rnh_walktree_from() above, and those that actually are children of
- * the late parent (passed in as VP here) are themselves deleted.
- */
-static int
-rt_fixdelete(struct radix_node *rn, void *vp)
-{
- struct rtentry *rt = RNTORT(rn);
- struct rtentry *rt0 = vp;
-
- if (rt->rt_parent == rt0 &&
- !(rt->rt_flags & (RTF_PINNED | RTF_CLONING))) {
- return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt),
- rt->rt_flags|RTF_RNH_LOCKED, NULL, rt->rt_fibnum);
- }
- return 0;
-}
-
-/*
- * This routine is called from rt_setgate() to do the analogous thing for
- * adds and changes. There is the added complication in this case of a
- * middle insert; i.e., insertion of a new network route between an older
- * network route and (cloned) host routes. For this reason, a simple check
- * of rt->rt_parent is insufficient; each candidate route must be tested
- * against the (mask, value) of the new route (passed as before in vp)
- * to see if the new route matches it.
- *
- * XXX - it may be possible to do fixdelete() for changes and reserve this
- * routine just for adds. I'm not sure why I thought it was necessary to do
- * changes this way.
- */
-
-static int
-rt_fixchange(struct radix_node *rn, void *vp)
-{
- struct rtentry *rt = RNTORT(rn);
- struct rtfc_arg *ap = vp;
- struct rtentry *rt0 = ap->rt0;
- struct radix_node_head *rnh = ap->rnh;
- u_char *xk1, *xm1, *xk2, *xmp;
- int i, len, mlen;
-
- /* make sure we have a parent, and route is not pinned or cloning */
- if (!rt->rt_parent ||
- (rt->rt_flags & (RTF_PINNED | RTF_CLONING)))
- return 0;
-
- if (rt->rt_parent == rt0) /* parent match */
- goto delete_rt;
- /*
- * There probably is a function somewhere which does this...
- * if not, there should be.
- */
- len = imin(rt_key(rt0)->sa_len, rt_key(rt)->sa_len);
-
- xk1 = (u_char *)rt_key(rt0);
- xm1 = (u_char *)rt_mask(rt0);
- xk2 = (u_char *)rt_key(rt);
-
- /* avoid applying a less specific route */
- xmp = (u_char *)rt_mask(rt->rt_parent);
- mlen = rt_key(rt->rt_parent)->sa_len;
- if (mlen > rt_key(rt0)->sa_len) /* less specific route */
- return 0;
- for (i = rnh->rnh_treetop->rn_offset; i < mlen; i++)
- if ((xmp[i] & ~(xmp[i] ^ xm1[i])) != xmp[i])
- return 0; /* less specific route */
-
- for (i = rnh->rnh_treetop->rn_offset; i < len; i++)
- if ((xk2[i] & xm1[i]) != xk1[i])
- return 0; /* no match */
-
- /*
- * OK, this node is a clone, and matches the node currently being
- * changed/added under the node's mask. So, get rid of it.
- */
-delete_rt:
- return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL,
- rt_mask(rt), rt->rt_flags, NULL, rt->rt_fibnum);
-}
-
int
rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate)
{
INIT_VNET_NET(curvnet);
/* XXX dst may be overwritten, can we move this to below */
+ int dlen = SA_SIZE(dst), glen = SA_SIZE(gate);
+#ifdef INVARIANTS
struct radix_node_head *rnh =
V_rt_tables[rt->rt_fibnum][dst->sa_family];
- int dlen = SA_SIZE(dst), glen = SA_SIZE(gate);
+#endif
-again:
RT_LOCK_ASSERT(rt);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
/*
- * A host route with the destination equal to the gateway
- * will interfere with keeping LLINFO in the routing
- * table, so disallow it.
- */
- if (((rt->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) ==
- (RTF_HOST|RTF_GATEWAY)) &&
- dst->sa_len == gate->sa_len &&
- bcmp(dst, gate, dst->sa_len) == 0) {
- /*
- * The route might already exist if this is an RTM_CHANGE
- * or a routing redirect, so try to delete it.
- */
- if (rt_key(rt))
- rtexpunge(rt);
- return EADDRNOTAVAIL;
- }
-
- /*
- * Cloning loop avoidance in case of bad configuration.
- */
- if (rt->rt_flags & RTF_GATEWAY) {
- struct rtentry *gwrt;
-
- RT_UNLOCK(rt); /* XXX workaround LOR */
- gwrt = rtalloc1_fib(gate, 1, RTF_RNH_LOCKED, rt->rt_fibnum);
- if (gwrt == rt) {
- RT_REMREF(rt);
- return (EADDRINUSE); /* failure */
- }
- /*
- * Try to reacquire the lock on rt, and if it fails,
- * clean state and restart from scratch.
- */
- if (!RT_TRYLOCK(rt)) {
- RTFREE_LOCKED(gwrt);
- RT_LOCK(rt);
- goto again;
- }
- /*
- * If there is already a gwroute, then drop it. If we
- * are asked to replace route with itself, then do
- * not leak its refcounter.
- */
- if (rt->rt_gwroute != NULL) {
- if (rt->rt_gwroute == gwrt) {
- RT_REMREF(rt->rt_gwroute);
- } else
- RTFREE(rt->rt_gwroute);
- }
-
- if ((rt->rt_gwroute = gwrt) != NULL)
- RT_UNLOCK(rt->rt_gwroute);
- }
-
- /*
* Prepare to store the gateway in rt->rt_gateway.
* Both dst and gateway are stored one after the other in the same
* malloc'd chunk. If we have room, we can reuse the old buffer,
@@ -1446,21 +1105,7 @@ again:
*/
bcopy(gate, rt->rt_gateway, glen);
- /*
- * This isn't going to do anything useful for host routes, so
- * don't bother. Also make sure we have a reasonable mask
- * (we don't yet have one during adds).
- */
- if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
- struct rtfc_arg arg;
-
- arg.rnh = rnh;
- arg.rt0 = rt;
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixchange, &arg);
- }
-
- return 0;
+ return (0);
}
static void
@@ -1500,6 +1145,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
char tempbuf[_SOCKADDR_TMPSIZE];
int didwork = 0;
int a_failure = 0;
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
if (flags & RTF_HOST) {
dst = ifa->ifa_dstaddr;
@@ -1604,7 +1250,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
info.rti_ifa = ifa;
info.rti_flags = flags | ifa->ifa_flags;
info.rti_info[RTAX_DST] = dst;
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD)
+ info.rti_info[RTAX_GATEWAY] =
+ (struct sockaddr *)&null_sdl;
+ else
+ info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
info.rti_info[RTAX_NETMASK] = netmask;
error = rtrequest1_fib(cmd, &info, &rt, fibnum);
if (error == 0 && rt != NULL) {
@@ -1628,6 +1281,15 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
rt->rt_ifa = ifa;
}
#endif
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD) {
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
+ rt->rt_ifp->if_type;
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
+ rt->rt_ifp->if_index;
+ }
rt_newaddrmsg(cmd, ifa, error, rt);
if (cmd == RTM_DELETE) {
/*
@@ -1696,147 +1358,5 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
return (rtinit1(ifa, cmd, flags, fib));
}
-/*
- * rt_check() is invoked on each layer 2 output path, prior to
- * encapsulating outbound packets.
- *
- * The function is mostly used to find a routing entry for the gateway,
- * which in some protocol families could also point to the link-level
- * address for the gateway itself (the side effect of revalidating the
- * route to the destination is rather pointless at this stage, we did it
- * already a moment before in the pr_output() routine to locate the ifp
- * and gateway to use).
- *
- * When we remove the layer-3 to layer-2 mapping tables from the
- * routing table, this function can be removed.
- *
- * === On input ===
- * *dst is the address of the NEXT HOP (which coincides with the
- * final destination if directly reachable);
- * *lrt0 points to the cached route to the final destination;
- * *lrt is not meaningful;
- * (*lrt0 has no ref held on it by us so REMREF is not needed.
- * Refs only account for major structural references and not usages,
- * which is actually a bit of a problem.)
- *
- * === Operation ===
- * If the route is marked down try to find a new route. If the route
- * to the gateway is gone, try to setup a new route. Otherwise,
- * if the route is marked for packets to be rejected, enforce that.
- * Note that rtalloc returns an rtentry with an extra REF that we may
- * need to lose.
- *
- * === On return ===
- * *dst is unchanged;
- * *lrt0 points to the (possibly new) route to the final destination
- * *lrt points to the route to the next hop [LOCKED]
- *
- * Their values are meaningful ONLY if no error is returned.
- *
- * To follow this you have to remember that:
- * RT_REMREF reduces the reference count by 1 but doesn't check it for 0 (!)
- * RTFREE_LOCKED includes an RT_REMREF (or an rtfree if refs == 1)
- * and an RT_UNLOCK
- * RTFREE does an RT_LOCK and an RTFREE_LOCKED
- * The gwroute pointer counts as a reference on the rtentry to which it points.
- * so when we add it we use the ref that rtalloc gives us and when we lose it
- * we need to remove the reference.
- * RT_TEMP_UNLOCK does an RT_ADDREF before freeing the lock, and
- * RT_RELOCK locks it (it can't have gone away due to the ref) and
- * drops the ref, possibly freeing it and zeroing the pointer if
- * the ref goes to 0 (unlocking in the process).
- */
-int
-rt_check(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst)
-{
- struct rtentry *rt;
- struct rtentry *rt0;
- u_int fibnum;
-
- KASSERT(*lrt0 != NULL, ("rt_check"));
- rt0 = *lrt0;
- rt = NULL;
- fibnum = rt0->rt_fibnum;
-
- /* NB: the locking here is tortuous... */
- RT_LOCK(rt0);
-retry:
- if (rt0 && (rt0->rt_flags & RTF_UP) == 0) {
- /* Current rt0 is useless, try get a replacement. */
- RT_UNLOCK(rt0);
- rt0 = NULL;
- }
- if (rt0 == NULL) {
- rt0 = rtalloc1_fib(dst, 1, 0UL, fibnum);
- if (rt0 == NULL) {
- return (EHOSTUNREACH);
- }
- RT_REMREF(rt0); /* don't need the reference. */
- }
-
- if (rt0->rt_flags & RTF_GATEWAY) {
- if ((rt = rt0->rt_gwroute) != NULL) {
- RT_LOCK(rt); /* NB: gwroute */
- if ((rt->rt_flags & RTF_UP) == 0) {
- /* gw route is dud. ignore/lose it */
- RTFREE_LOCKED(rt); /* unref (&unlock) gwroute */
- rt = rt0->rt_gwroute = NULL;
- }
- }
-
- if (rt == NULL) { /* NOT AN ELSE CLAUSE */
- RT_TEMP_UNLOCK(rt0); /* MUST return to undo this */
- rt = rtalloc1_fib(rt0->rt_gateway, 1, 0UL, fibnum);
- if ((rt == rt0) || (rt == NULL)) {
- /* the best we can do is not good enough */
- if (rt) {
- RT_REMREF(rt); /* assumes ref > 0 */
- RT_UNLOCK(rt);
- }
- RTFREE(rt0); /* lock, unref, (unlock) */
- return (ENETUNREACH);
- }
- /*
- * Relock it and lose the added reference.
- * All sorts of things could have happenned while we
- * had no lock on it, so check for them.
- */
- RT_RELOCK(rt0);
- if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0))
- /* Ru-roh.. what we had is no longer any good */
- goto retry;
- /*
- * While we were away, someone replaced the gateway.
- * Since a reference count is involved we can't just
- * overwrite it.
- */
- if (rt0->rt_gwroute) {
- if (rt0->rt_gwroute != rt) {
- RTFREE_LOCKED(rt);
- goto retry;
- }
- } else {
- rt0->rt_gwroute = rt;
- }
- }
- RT_LOCK_ASSERT(rt);
- RT_UNLOCK(rt0);
- } else {
- /* think of rt as having the lock from now on.. */
- rt = rt0;
- }
- /* XXX why are we inspecting rmx_expire? */
- if ((rt->rt_flags & RTF_REJECT) &&
- (rt->rt_rmx.rmx_expire == 0 ||
- time_uptime < rt->rt_rmx.rmx_expire)) {
- RT_UNLOCK(rt);
- return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
- }
-
- *lrt = rt;
- *lrt0 = rt0;
- return (0);
-}
-
/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
diff --git a/sys/net/route.h b/sys/net/route.h
index fb8df39..5062198 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -135,15 +135,11 @@ struct rtentry {
#define rt_key(r) (*((struct sockaddr **)(&(r)->rt_nodes->rn_key)))
#define rt_mask(r) (*((struct sockaddr **)(&(r)->rt_nodes->rn_mask)))
struct sockaddr *rt_gateway; /* value */
- u_long rt_flags; /* up/down?, host/net */
+ int rt_flags; /* up/down?, host/net */
+ int rt_refcnt; /* # held references */
struct ifnet *rt_ifp; /* the answer: interface to use */
struct ifaddr *rt_ifa; /* the answer: interface address to use */
struct rt_metrics_lite rt_rmx; /* metrics used by rx'ing protocols */
- long rt_refcnt; /* # held references */
- struct sockaddr *rt_genmask; /* for generation of cloned routes */
- caddr_t rt_llinfo; /* pointer to link level info cache */
- struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
- struct rtentry *rt_parent; /* cloning parent of this route */
u_int rt_fibnum; /* which FIB */
#ifdef _KERNEL
/* XXX ugly, user apps use this definition but don't have a mtx def */
@@ -175,9 +171,9 @@ struct ortentry {
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
#define RTF_DONE 0x40 /* message confirmed */
/* 0x80 unused, was RTF_DELCLONE */
-#define RTF_CLONING 0x100 /* generate new routes on use */
+/* 0x100 unused, was RTF_CLONING */
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
-#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
+/* 0x400 unused, was RTF_LLINFO */
#define RTF_STATIC 0x800 /* manually added */
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
@@ -188,7 +184,7 @@ struct ortentry {
#define RTF_PRCLONING 0x10000 /* unused, for compatibility */
#endif
-#define RTF_WASCLONED 0x20000 /* route generated through cloning */
+/* 0x20000 unused, was RTF_WASCLONED */
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
/* 0x80000 unused */
#define RTF_PINNED 0x100000 /* future use */
@@ -326,14 +322,14 @@ struct rt_addrinfo {
#define RT_ADDREF(_rt) do { \
RT_LOCK_ASSERT(_rt); \
KASSERT((_rt)->rt_refcnt >= 0, \
- ("negative refcnt %ld", (_rt)->rt_refcnt)); \
+ ("negative refcnt %d", (_rt)->rt_refcnt)); \
(_rt)->rt_refcnt++; \
} while (0)
#define RT_REMREF(_rt) do { \
RT_LOCK_ASSERT(_rt); \
KASSERT((_rt)->rt_refcnt > 0, \
- ("bogus refcnt %ld", (_rt)->rt_refcnt)); \
+ ("bogus refcnt %d", (_rt)->rt_refcnt)); \
(_rt)->rt_refcnt--; \
} while (0)
@@ -409,7 +405,6 @@ void rtredirect(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *);
int rtrequest(int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **);
-int rtrequest1(int, struct rt_addrinfo *, struct rtentry **);
/* defaults to "all" FIBs */
int rtinit_fib(struct ifaddr *, int, int);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 5003b03..30591c7 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -53,6 +53,7 @@
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/raw_cb.h>
#include <net/route.h>
@@ -496,19 +497,6 @@ route_output(struct mbuf *m, struct socket *so)
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
senderr(EINVAL);
- if (info.rti_info[RTAX_GENMASK]) {
- struct radix_node *t;
- t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1);
- if (t != NULL &&
- bcmp((char *)(void *)info.rti_info[RTAX_GENMASK] + 1,
- (char *)(void *)t->rn_key + 1,
- ((struct sockaddr *)t->rn_key)->sa_len - 1) == 0)
- info.rti_info[RTAX_GENMASK] =
- (struct sockaddr *)t->rn_key;
- else
- senderr(ENOBUFS);
- }
-
/*
* Verify that the caller has the appropriate privilege; RTM_GET
* is the only operation the non-superuser is allowed.
@@ -526,6 +514,11 @@ route_output(struct mbuf *m, struct socket *so)
if (info.rti_info[RTAX_GATEWAY] == NULL)
senderr(EINVAL);
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1_fib(RTM_ADD, &info, &saved_nrt,
so->so_fibnum);
if (error == 0 && saved_nrt) {
@@ -534,13 +527,18 @@ route_output(struct mbuf *m, struct socket *so)
&rtm->rtm_rmx, &saved_nrt->rt_rmx);
rtm->rtm_index = saved_nrt->rt_ifp->if_index;
RT_REMREF(saved_nrt);
- saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
RT_UNLOCK(saved_nrt);
}
break;
case RTM_DELETE:
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY] &&
+ (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt,
so->so_fibnum);
if (error == 0) {
@@ -612,7 +610,7 @@ route_output(struct mbuf *m, struct socket *so)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
+ info.rti_info[RTAX_GENMASK] = 0;
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
ifp = rt->rt_ifp;
if (ifp) {
@@ -699,8 +697,7 @@ route_output(struct mbuf *m, struct socket *so)
RT_UNLOCK(rt);
senderr(error);
}
- if (!(rt->rt_flags & RTF_LLINFO))
- rt->rt_flags |= RTF_GATEWAY;
+ rt->rt_flags |= RTF_GATEWAY;
}
if (info.rti_ifa != NULL &&
info.rti_ifa != rt->rt_ifa) {
@@ -718,8 +715,6 @@ route_output(struct mbuf *m, struct socket *so)
rtm->rtm_index = rt->rt_ifp->if_index;
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
- if (info.rti_info[RTAX_GENMASK])
- rt->rt_genmask = info.rti_info[RTAX_GENMASK];
/* FALLTHROUGH */
case RTM_LOCK:
/* We don't support locks anymore */
@@ -1261,7 +1256,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
+ info.rti_info[RTAX_GENMASK] = 0;
if (rt->rt_ifp) {
info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
@@ -1440,6 +1435,11 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
RADIX_NODE_HEAD_UNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
+ /*
+ * take care of llinfo entries
+ */
+ if (w.w_op == NET_RT_FLAGS)
+ error = lltable_sysctl_dumparp(af, w.w_req);
break;
case NET_RT_IFLIST:
OpenPOWER on IntegriCloud