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;

Reply via email to