Annotation of embedaddon/quagga/babeld/neighbour.c, revision 1.1.1.1

1.1       misho       1: /*  
                      2:  *  This file is free software: you may copy, redistribute and/or modify it  
                      3:  *  under the terms of the GNU General Public License as published by the  
                      4:  *  Free Software Foundation, either version 2 of the License, or (at your  
                      5:  *  option) any later version.  
                      6:  *  
                      7:  *  This file is distributed in the hope that it will be useful, but  
                      8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
                      9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
                     10:  *  General Public License for more details.  
                     11:  *  
                     12:  *  You should have received a copy of the GNU General Public License  
                     13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
                     14:  *  
                     15:  * This file incorporates work covered by the following copyright and  
                     16:  * permission notice:  
                     17:  *
                     18: Copyright (c) 2007, 2008 by Juliusz Chroboczek
                     19: 
                     20: Permission is hereby granted, free of charge, to any person obtaining a copy
                     21: of this software and associated documentation files (the "Software"), to deal
                     22: in the Software without restriction, including without limitation the rights
                     23: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     24: copies of the Software, and to permit persons to whom the Software is
                     25: furnished to do so, subject to the following conditions:
                     26: 
                     27: The above copyright notice and this permission notice shall be included in
                     28: all copies or substantial portions of the Software.
                     29: 
                     30: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     31: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     32: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
                     33: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     34: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     35: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     36: THE SOFTWARE.
                     37: */
                     38: 
                     39: #include <stdlib.h>
                     40: #include <string.h>
                     41: #include <stdio.h>
                     42: #include <sys/time.h>
                     43: #include <time.h>
                     44: 
                     45: #include <zebra.h>
                     46: #include "if.h"
                     47: 
                     48: #include "babel_main.h"
                     49: #include "babeld.h"
                     50: #include "util.h"
                     51: #include "babel_interface.h"
                     52: #include "neighbour.h"
                     53: #include "source.h"
                     54: #include "route.h"
                     55: #include "message.h"
                     56: #include "resend.h"
                     57: 
                     58: struct neighbour *neighs = NULL;
                     59: 
                     60: static struct neighbour *
                     61: find_neighbour_nocreate(const unsigned char *address, struct interface *ifp)
                     62: {
                     63:     struct neighbour *neigh;
                     64:     FOR_ALL_NEIGHBOURS(neigh) {
                     65:         if(memcmp(address, neigh->address, 16) == 0 &&
                     66:            neigh->ifp == ifp)
                     67:             return neigh;
                     68:     }
                     69:     return NULL;
                     70: }
                     71: 
                     72: void
                     73: flush_neighbour(struct neighbour *neigh)
                     74: {
                     75:     flush_neighbour_routes(neigh);
                     76:     if(unicast_neighbour == neigh)
                     77:         flush_unicast(1);
                     78:     flush_resends(neigh);
                     79: 
                     80:     if(neighs == neigh) {
                     81:         neighs = neigh->next;
                     82:     } else {
                     83:         struct neighbour *previous = neighs;
                     84:         while(previous->next != neigh)
                     85:             previous = previous->next;
                     86:         previous->next = neigh->next;
                     87:     }
                     88:     free(neigh);
                     89: }
                     90: 
                     91: struct neighbour *
                     92: find_neighbour(const unsigned char *address, struct interface *ifp)
                     93: {
                     94:     struct neighbour *neigh;
                     95:     const struct timeval zero = {0, 0};
                     96: 
                     97:     neigh = find_neighbour_nocreate(address, ifp);
                     98:     if(neigh)
                     99:         return neigh;
                    100: 
                    101:     debugf(BABEL_DEBUG_COMMON,"Creating neighbour %s on %s.",
                    102:            format_address(address), ifp->name);
                    103: 
                    104:     neigh = malloc(sizeof(struct neighbour));
                    105:     if(neigh == NULL) {
                    106:         zlog_err("malloc(neighbour): %s", safe_strerror(errno));
                    107:         return NULL;
                    108:     }
                    109: 
                    110:     neigh->hello_seqno = -1;
                    111:     memcpy(neigh->address, address, 16);
                    112:     neigh->reach = 0;
                    113:     neigh->txcost = INFINITY;
                    114:     neigh->ihu_time = babel_now;
                    115:     neigh->hello_time = zero;
                    116:     neigh->hello_interval = 0;
                    117:     neigh->ihu_interval = 0;
                    118:     neigh->ifp = ifp;
                    119:     neigh->next = neighs;
                    120:     neighs = neigh;
                    121:     send_hello(ifp);
                    122:     return neigh;
                    123: }
                    124: 
                    125: /* Recompute a neighbour's rxcost.  Return true if anything changed.
                    126:    This does not call local_notify_neighbour, see update_neighbour_metric. */
                    127: int
                    128: update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
                    129: {
                    130:     int missed_hellos;
                    131:     int rc = 0;
                    132: 
                    133:     if(hello < 0) {
                    134:         if(neigh->hello_interval <= 0)
                    135:             return rc;
                    136:         missed_hellos =
                    137:             ((int)timeval_minus_msec(&babel_now, &neigh->hello_time) -
                    138:              neigh->hello_interval * 7) /
                    139:             (neigh->hello_interval * 10);
                    140:         if(missed_hellos <= 0)
                    141:             return rc;
                    142:         timeval_add_msec(&neigh->hello_time, &neigh->hello_time,
                    143:                           missed_hellos * neigh->hello_interval * 10);
                    144:     } else {
                    145:         if(neigh->hello_seqno >= 0 && neigh->reach > 0) {
                    146:             missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1;
                    147:             if(missed_hellos < -8) {
                    148:                 /* Probably a neighbour that rebooted and lost its seqno.
                    149:                    Reboot the universe. */
                    150:                 neigh->reach = 0;
                    151:                 missed_hellos = 0;
                    152:                 rc = 1;
                    153:             } else if(missed_hellos < 0) {
                    154:                 if(hello_interval > neigh->hello_interval) {
                    155:                     /* This neighbour has increased its hello interval,
                    156:                        and we didn't notice. */
                    157:                     neigh->reach <<= -missed_hellos;
                    158:                     missed_hellos = 0;
                    159:                 } else {
                    160:                     /* Late hello.  Probably due to the link layer buffering
                    161:                        packets during a link outage.  Ignore it, but reset
                    162:                        the expected seqno. */
                    163:                     neigh->hello_seqno = hello;
                    164:                     hello = -1;
                    165:                     missed_hellos = 0;
                    166:                 }
                    167:                 rc = 1;
                    168:             }
                    169:         } else {
                    170:             missed_hellos = 0;
                    171:         }
                    172:         neigh->hello_time = babel_now;
                    173:         neigh->hello_interval = hello_interval;
                    174:     }
                    175: 
                    176:     if(missed_hellos > 0) {
                    177:         neigh->reach >>= missed_hellos;
                    178:         neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos);
                    179:         missed_hellos = 0;
                    180:         rc = 1;
                    181:     }
                    182: 
                    183:     if(hello >= 0) {
                    184:         neigh->hello_seqno = hello;
                    185:         neigh->reach >>= 1;
                    186:         neigh->reach |= 0x8000;
                    187:         if((neigh->reach & 0xFC00) != 0xFC00)
                    188:             rc = 1;
                    189:     }
                    190: 
                    191:     /* Make sure to give neighbours some feedback early after association */
                    192:     if((neigh->reach & 0xBF00) == 0x8000) {
                    193:         /* A new neighbour */
                    194:         send_hello(neigh->ifp);
                    195:     } else {
                    196:         /* Don't send hellos, in order to avoid a positive feedback loop. */
                    197:         int a = (neigh->reach & 0xC000);
                    198:         int b = (neigh->reach & 0x3000);
                    199:         if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
                    200:             /* Reachability is either 1100 or 0011 */
                    201:             send_self_update(neigh->ifp);
                    202:         }
                    203:     }
                    204: 
                    205:     if((neigh->reach & 0xFC00) == 0xC000) {
                    206:         /* This is a newish neighbour, let's request a full route dump.
                    207:            We ought to avoid this when the network is dense */
                    208:         send_unicast_request(neigh, NULL, 0);
                    209:         send_ihu(neigh, NULL);
                    210:     }
                    211:     return rc;
                    212: }
                    213: 
                    214: static int
                    215: reset_txcost(struct neighbour *neigh)
                    216: {
                    217:     unsigned delay;
                    218: 
                    219:     delay = timeval_minus_msec(&babel_now, &neigh->ihu_time);
                    220: 
                    221:     if(neigh->ihu_interval > 0 && delay < neigh->ihu_interval * 10U * 3U)
                    222:         return 0;
                    223: 
                    224:     /* If we're losing a lot of packets, we probably lost an IHU too */
                    225:     if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 ||
                    226:        (neigh->ihu_interval > 0 &&
                    227:         delay >= neigh->ihu_interval * 10U * 10U)) {
                    228:         neigh->txcost = INFINITY;
                    229:         neigh->ihu_time = babel_now;
                    230:         return 1;
                    231:     }
                    232: 
                    233:     return 0;
                    234: }
                    235: 
                    236: unsigned
                    237: neighbour_txcost(struct neighbour *neigh)
                    238: {
                    239:     return neigh->txcost;
                    240: }
                    241: 
                    242: unsigned
                    243: check_neighbours()
                    244: {
                    245:     struct neighbour *neigh;
                    246:     int changed, rc;
                    247:     unsigned msecs = 50000;
                    248: 
                    249:     debugf(BABEL_DEBUG_COMMON,"Checking neighbours.");
                    250: 
                    251:     neigh = neighs;
                    252:     while(neigh) {
                    253:         changed = update_neighbour(neigh, -1, 0);
                    254: 
                    255:         if(neigh->reach == 0 ||
                    256:            neigh->hello_time.tv_sec > babel_now.tv_sec || /* clock stepped */
                    257:            timeval_minus_msec(&babel_now, &neigh->hello_time) > 300000) {
                    258:             struct neighbour *old = neigh;
                    259:             neigh = neigh->next;
                    260:             flush_neighbour(old);
                    261:             continue;
                    262:         }
                    263: 
                    264:         rc = reset_txcost(neigh);
                    265:         changed = changed || rc;
                    266: 
                    267:         update_neighbour_metric(neigh, changed);
                    268: 
                    269:         if(neigh->hello_interval > 0)
                    270:             msecs = MIN(msecs, neigh->hello_interval * 10U);
                    271:         if(neigh->ihu_interval > 0)
                    272:             msecs = MIN(msecs, neigh->ihu_interval * 10U);
                    273:         neigh = neigh->next;
                    274:     }
                    275: 
                    276:     return msecs;
                    277: }
                    278: 
                    279: unsigned
                    280: neighbour_rxcost(struct neighbour *neigh)
                    281: {
                    282:     unsigned delay;
                    283:     unsigned short reach = neigh->reach;
                    284: 
                    285:     delay = timeval_minus_msec(&babel_now, &neigh->hello_time);
                    286: 
                    287:     if((reach & 0xFFF0) == 0 || delay >= 180000) {
                    288:         return INFINITY;
                    289:     } else if(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ) {
                    290:         int sreach =
                    291:             ((reach & 0x8000) >> 2) +
                    292:             ((reach & 0x4000) >> 1) +
                    293:             (reach & 0x3FFF);
                    294:         /* 0 <= sreach <= 0x7FFF */
                    295:         int cost = (0x8000 * babel_get_if_nfo(neigh->ifp)->cost) / (sreach + 1);
                    296:         /* cost >= interface->cost */
                    297:         if(delay >= 40000)
                    298:             cost = (cost * (delay - 20000) + 10000) / 20000;
                    299:         return MIN(cost, INFINITY);
                    300:     } else {
                    301:         /* To lose one hello is a misfortune, to lose two is carelessness. */
                    302:         if((reach & 0xC000) == 0xC000)
                    303:             return babel_get_if_nfo(neigh->ifp)->cost;
                    304:         else if((reach & 0xC000) == 0)
                    305:             return INFINITY;
                    306:         else if((reach & 0x2000))
                    307:             return babel_get_if_nfo(neigh->ifp)->cost;
                    308:         else
                    309:             return INFINITY;
                    310:     }
                    311: }
                    312: 
                    313: unsigned
                    314: neighbour_cost(struct neighbour *neigh)
                    315: {
                    316:     unsigned a, b;
                    317: 
                    318:     if(!if_up(neigh->ifp))
                    319:         return INFINITY;
                    320: 
                    321:     a = neighbour_txcost(neigh);
                    322: 
                    323:     if(a >= INFINITY)
                    324:         return INFINITY;
                    325: 
                    326:     b = neighbour_rxcost(neigh);
                    327:     if(b >= INFINITY)
                    328:         return INFINITY;
                    329: 
                    330:     if(!(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ)
                    331:        || (a < 256 && b < 256)) {
                    332:         return a;
                    333:     } else {
                    334:         /* a = 256/alpha, b = 256/beta, where alpha and beta are the expected
                    335:            probabilities of a packet getting through in the direct and reverse
                    336:            directions. */
                    337:         a = MAX(a, 256);
                    338:         b = MAX(b, 256);
                    339:         /* 1/(alpha * beta), which is just plain ETX. */
                    340:         /* Since a and b are capped to 16 bits, overflow is impossible. */
                    341:         return (a * b + 128) >> 8;
                    342:     }
                    343: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>