On Tue, Nov 06, 2007 at 06:26:47PM +0100, Tony Sarendal wrote: > New version. Less duplication and a nice feature as bonus. > With softreconfig in enabled the looped prefixes are accepted > into the Adj-RIB-In. > > This means that I can tell if my neighbor AS is using > a path via myself. Either I'm tired or that is cool. > > router-02# bgpctl show rib 192.168.0.0 > flags: * = Valid, > = Selected, I = via IBGP, A = Announced > origin: i = IGP, e = EGP, ? = Incomplete > > flags destination gateway lpref med aspath origin > *> 192.168.0.0/16 192.168.100.5 100 0 65100 i > * 192.168.0.0/16 172.17.1.1 100 0 65200 65100 i > * 192.168.0.0/16 172.17.1.5 100 0 65200 65200 65200 > 65200 65100 i > router-02# > > I now kill the peering that 65200 has to 65100, removing their > direct path to 192.168.0.0/16. > > router-02# bgpctl show rib 192.168.0.0 > flags: * = Valid, > = Selected, I = via IBGP, A = Announced > origin: i = IGP, e = EGP, ? = Incomplete > > flags destination gateway lpref med aspath origin > *> 192.168.0.0/16 192.168.100.5 100 0 65100 i > router-02# > > Sweet, the looping issue is gone. > Here is the bonus: > > router-02# bgpctl show rib neigh 172.17.1.5 in | grep 65300 > * 172.17.0.2/32 172.17.1.5 100 0 65200 65300 i > * 192.168.0.0/16 172.17.1.5 100 0 65200 65300 65100 i > * 192.168.100.4/30 172.17.1.5 100 0 65200 65300 i > router-02# > > I now see the paths that the peer uses my network to access. > Note that this depends a bit on remote implementation. > I think this works agains a cisco router. > > /Tony > > > Index: rde.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v > retrieving revision 1.228 > diff -u -r1.228 rde.c > --- rde.c 16 Sep 2007 15:20:50 -0000 1.228 > +++ rde.c 6 Nov 2007 17:08:50 -0000 > @@ -919,12 +919,6 @@ > /* shift to NLRI information */ > p += 2 + attrpath_len; > > - /* aspath needs to be loop free nota bene this is not a hard error */ > - if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, conf->as)) { > - error = 0; > - goto done; > - } > - > /* parse nlri prefix */ > while (nlri_len > 0) { > if ((pos = rde_update_get_prefix(p, nlri_len, &prefix, > @@ -977,10 +971,18 @@ > if (fasp == NULL) > fasp = asp; > > - rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, > - &prefix, prefixlen); > - path_update(peer, fasp, &prefix, prefixlen, F_LOCAL); > - > + rde_update_log("update", peer, > + &fasp->nexthop->exit_nexthop,&prefix, > + prefixlen); > + /* handle an update with loop as a withdraw */ > + if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, > + conf->as)) > + prefix_remove(peer, &prefix, prefixlen, > + F_LOCAL); > + else > + path_update(peer, fasp, &prefix, prefixlen, > + F_LOCAL); > + > /* free modified aspath */ > if (fasp != asp) > path_put(fasp); > @@ -1075,9 +1077,15 @@ > > rde_update_log("update", peer, > &asp->nexthop->exit_nexthop, > - &prefix, prefixlen); > - path_update(peer, fasp, &prefix, prefixlen, > - F_LOCAL); > + &prefix, prefixlen); > + /* handle an update with loop as a withdraw */ > + if (peer->conf.ebgp && > + !aspath_loopfree(asp->aspath,conf->as)) > + prefix_remove(peer, &prefix, > + prefixlen,F_LOCAL); > + else > + path_update(peer, fasp, &prefix, > + prefixlen,F_LOCAL); > > /* free modified aspath */ > if (fasp != asp)
I looked a bit closer at this problem and the RFC mentions that pathes with loops need to be inserted into the RIB and will be ignored in phase 2 of the decision process. So this diff does just about that. It does not remove any prefix if there is a loop but instead is ignoring them during the route decision process. This seems to work for me but I'm currently unable to do larger tests. -- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.228 diff -u -p -r1.228 rde.c --- rde.c 16 Sep 2007 15:20:50 -0000 1.228 +++ rde.c 6 Nov 2007 18:27:42 -0000 @@ -920,10 +920,8 @@ rde_update_dispatch(struct imsg *imsg) p += 2 + attrpath_len; /* aspath needs to be loop free nota bene this is not a hard error */ - if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, conf->as)) { - error = 0; - goto done; - } + if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, conf->as)) + asp->flags |= F_ATTR_ASLOOP; /* parse nlri prefix */ while (nlri_len > 0) { Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.100 diff -u -p -r1.100 rde.h --- rde.h 1 Jun 2007 04:17:30 -0000 1.100 +++ rde.h 6 Nov 2007 19:17:56 -0000 @@ -154,6 +154,7 @@ LIST_HEAD(prefix_head, prefix); #define F_ATTR_MP_REACH 0x00040 #define F_ATTR_MP_UNREACH 0x00080 #define F_ATTR_AS4BYTE_NEW 0x00100 /* NEW_ASPATH or NEW_AGGREGATOR */ +#define F_ATTR_ASLOOP 0x00200 #define F_PREFIX_ANNOUNCED 0x01000 #define F_NEXTHOP_REJECT 0x02000 #define F_NEXTHOP_BLACKHOLE 0x04000 Index: rde_decide.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v retrieving revision 1.48 diff -u -p -r1.48 rde_decide.c --- rde_decide.c 11 May 2007 11:27:59 -0000 1.48 +++ rde_decide.c 12 Nov 2007 05:43:20 -0000 @@ -120,6 +120,12 @@ prefix_cmp(struct prefix *p1, struct pre return (-1); if (!(p2->flags & F_LOCAL)) return (1); + + /* only loop free pathes are eligible */ + if (p1->flags & F_ATTR_ASLOOP) + return (-1); + if (p2->flags & F_ATTR_ASLOOP) + return (1); asp1 = p1->aspath; asp2 = p2->aspath; @@ -239,8 +245,8 @@ prefix_evaluate(struct prefix *p, struct xp = LIST_FIRST(&pte->prefix_h); if (xp == NULL || !(xp->flags & F_LOCAL) || - (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state != - NEXTHOP_REACH)) + (xp->flags & F_ATTR_ASLOOP) || (xp->aspath->nexthop != NULL && + xp->aspath->nexthop->state != NEXTHOP_REACH)) /* xp is ineligible */ xp = NULL;