Claudio Jeker([email protected]) on 2021.01.13 13:10:23 +0100:
> This is another cleanup round of the route decision process.
> This time focusing on prefix_cmp(). Make sure that when using
> return (a - b) that the results always fits in an int type.
> Also make sure the check of the remote_addr at the end is done
> properly. The result is probably the same but this is the same
> way it is done in many other places.
> 
> Unless I made a mistake the result should still be the same.

ok


> -- 
> :wq Claudio
> 
> ? obj
> Index: rde_decide.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v
> retrieving revision 1.79
> diff -u -p -r1.79 rde_decide.c
> --- rde_decide.c      13 Jan 2021 11:34:01 -0000      1.79
> +++ rde_decide.c      13 Jan 2021 12:08:21 -0000
> @@ -113,12 +113,12 @@ prefix_cmp(struct prefix *p1, struct pre
>       struct rde_peer         *peer1, *peer2;
>       struct attr             *a;
>       u_int32_t                p1id, p2id;
> -     int                      p1cnt, p2cnt;
> +     int                      p1cnt, p2cnt, i;
>  
>       if (p1 == NULL)
> -             return (-1);
> +             return -1;
>       if (p2 == NULL)
> -             return (1);
> +             return 1;
>  
>       asp1 = prefix_aspath(p1);
>       asp2 = prefix_aspath(p2);
> @@ -127,15 +127,15 @@ prefix_cmp(struct prefix *p1, struct pre
>  
>       /* pathes with errors are not eligible */
>       if (asp1 == NULL || asp1->flags & F_ATTR_PARSE_ERR)
> -             return (-1);
> +             return -1;
>       if (asp2 == NULL || asp2->flags & F_ATTR_PARSE_ERR)
> -             return (1);
> +             return 1;
>  
>       /* only loop free pathes are eligible */
>       if (asp1->flags & F_ATTR_LOOP)
> -             return (-1);
> +             return -1;
>       if (asp2->flags & F_ATTR_LOOP)
> -             return (1);
> +             return 1;
>  
>       /*
>        * 1. check if prefix is eligible a.k.a reachable
> @@ -144,14 +144,16 @@ prefix_cmp(struct prefix *p1, struct pre
>        */
>       if (prefix_nexthop(p2) != NULL &&
>           prefix_nexthop(p2)->state != NEXTHOP_REACH)
> -             return (1);
> +             return 1;
>       if (prefix_nexthop(p1) != NULL &&
>           prefix_nexthop(p1)->state != NEXTHOP_REACH)
> -             return (-1);
> +             return -1;
>  
>       /* 2. local preference of prefix, bigger is better */
> -     if ((asp1->lpref - asp2->lpref) != 0)
> -             return (asp1->lpref - asp2->lpref);
> +     if (asp1->lpref > asp2->lpref)
> +             return 1;
> +     if (asp1->lpref < asp2->lpref)
> +             return -1;
>  
>       /* 3. aspath count, the shorter the better */
>       if ((asp2->aspath->ascnt - asp1->aspath->ascnt) != 0)
> @@ -161,12 +163,19 @@ prefix_cmp(struct prefix *p1, struct pre
>       if ((asp2->origin - asp1->origin) != 0)
>               return (asp2->origin - asp1->origin);
>  
> -     /* 5. MED decision, only comparable between the same neighboring AS */
> -     if (rde_decisionflags() & BGPD_FLAG_DECISION_MED_ALWAYS ||
> -         aspath_neighbor(asp1->aspath) == aspath_neighbor(asp2->aspath))
> +     /*
> +      * 5. MED decision
> +      * Only comparable between the same neighboring AS or if
> +      * 'rde med compare always' is set.
> +      */
> +     if ((rde_decisionflags() & BGPD_FLAG_DECISION_MED_ALWAYS) ||
> +         aspath_neighbor(asp1->aspath) == aspath_neighbor(asp2->aspath)) {
>               /* lowest value wins */
> -             if ((asp2->med - asp1->med) != 0)
> -                     return (asp2->med - asp1->med);
> +             if (asp1->med < asp2->med)
> +                     return 1;
> +             if (asp1->med > asp2->med)
> +                     return -1;
> +     }
>  
>       /*
>        * 6. EBGP is cooler than IBGP
> @@ -187,8 +196,10 @@ prefix_cmp(struct prefix *p1, struct pre
>        * a metric that weights a prefix at a very late stage in the
>        * decision process.
>        */
> -     if ((asp1->weight - asp2->weight) != 0)
> -             return (asp1->weight - asp2->weight);
> +     if (asp1->weight > asp2->weight)
> +             return 1;
> +     if (asp1->weight < asp2->weight)
> +             return -1;
>  
>       /* 8. nexthop costs. NOT YET -> IGNORE */
>  
> @@ -196,9 +207,12 @@ prefix_cmp(struct prefix *p1, struct pre
>        * 9. older route (more stable) wins but only if route-age
>        * evaluation is enabled.
>        */
> -     if (rde_decisionflags() & BGPD_FLAG_DECISION_ROUTEAGE)
> -             if ((p2->lastchange - p1->lastchange) != 0)
> -                     return (p2->lastchange - p1->lastchange);
> +     if (rde_decisionflags() & BGPD_FLAG_DECISION_ROUTEAGE) {
> +             if (p1->lastchange < p2->lastchange) /* p1 is older */
> +                     return 1;
> +             if (p1->lastchange > p2->lastchange)
> +                     return -1;
> +     }
>  
>       /* 10. lowest BGP Id wins, use ORIGINATOR_ID if present */
>       if ((a = attr_optget(asp1, ATTR_ORIGINATOR_ID)) != NULL) {
> @@ -211,8 +225,10 @@ prefix_cmp(struct prefix *p1, struct pre
>               p2id = ntohl(p2id);
>       } else
>               p2id = peer2->remote_bgpid;
> -     if ((p2id - p1id) != 0)
> -             return (p2id - p1id);
> +     if (p1id < p2id)
> +             return 1;
> +     if (p1id > p2id)
> +             return -1;
>  
>       /* 11. compare CLUSTER_LIST length, shorter is better */
>       p1cnt = p2cnt = 0;
> @@ -224,10 +240,26 @@ prefix_cmp(struct prefix *p1, struct pre
>               return (p2cnt - p1cnt);
>  
>       /* 12. lowest peer address wins (IPv4 is better than IPv6) */
> -     if (memcmp(&peer1->remote_addr, &peer2->remote_addr,
> -         sizeof(peer1->remote_addr)) != 0)
> -             return (-memcmp(&peer1->remote_addr, &peer2->remote_addr,
> -                 sizeof(peer1->remote_addr)));
> +     if (peer1->remote_addr.aid < peer2->remote_addr.aid)
> +             return 1;
> +     if (peer1->remote_addr.aid > peer2->remote_addr.aid)
> +             return -1;
> +     switch (peer1->remote_addr.aid) {
> +     case AID_INET:
> +             i = memcmp(&peer1->remote_addr.v4, &peer2->remote_addr.v4,
> +                 sizeof(struct in_addr));
> +             break;
> +     case AID_INET6:
> +             i = memcmp(&peer1->remote_addr.v6, &peer2->remote_addr.v6,
> +                 sizeof(struct in6_addr));
> +             break;
> +     default:
> +             fatalx("%s: unknown af", __func__);
> +     }
> +     if (i < 0)
> +             return 1;
> +     if (i > 0)
> +             return -1;
>  
>       fatalx("Uh, oh a politician in the decision process");
>  }
> 

Reply via email to