Annotation of embedaddon/quagga/pimd/pim_upstream.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   PIM for Quagga
                      3:   Copyright (C) 2008  Everton da Silva Marques
                      4: 
                      5:   This program is free software; you can redistribute it and/or modify
                      6:   it under the terms of the GNU General Public License as published by
                      7:   the Free Software Foundation; either version 2 of the License, or
                      8:   (at your option) any later version.
                      9: 
                     10:   This program is distributed in the hope that it will be useful, but
                     11:   WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     13:   General Public License for more details.
                     14:   
                     15:   You should have received a copy of the GNU General Public License
                     16:   along with this program; see the file COPYING; if not, write to the
                     17:   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
                     18:   MA 02110-1301 USA
                     19:   
                     20:   $QuaggaId: $Format:%an, %ai, %h$ $
                     21: */
                     22: 
                     23: #include <zebra.h>
                     24: 
                     25: #include "zebra/rib.h"
                     26: 
                     27: #include "log.h"
                     28: #include "zclient.h"
                     29: #include "memory.h"
                     30: #include "thread.h"
                     31: #include "linklist.h"
                     32: 
                     33: #include "pimd.h"
                     34: #include "pim_pim.h"
                     35: #include "pim_str.h"
                     36: #include "pim_time.h"
                     37: #include "pim_iface.h"
                     38: #include "pim_join.h"
                     39: #include "pim_zlookup.h"
                     40: #include "pim_upstream.h"
                     41: #include "pim_ifchannel.h"
                     42: #include "pim_neighbor.h"
                     43: #include "pim_rpf.h"
                     44: #include "pim_zebra.h"
                     45: #include "pim_oil.h"
                     46: #include "pim_macro.h"
                     47: 
                     48: static void join_timer_start(struct pim_upstream *up);
                     49: static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up);
                     50: 
                     51: void pim_upstream_free(struct pim_upstream *up)
                     52: {
                     53:   XFREE(MTYPE_PIM_UPSTREAM, up);
                     54: }
                     55: 
                     56: static void upstream_channel_oil_detach(struct pim_upstream *up)
                     57: {
                     58:   if (up->channel_oil) {
                     59:     pim_channel_oil_del(up->channel_oil);
                     60:     up->channel_oil = 0;
                     61:   }
                     62: }
                     63: 
                     64: void pim_upstream_delete(struct pim_upstream *up)
                     65: {
                     66:   THREAD_OFF(up->t_join_timer);
                     67: 
                     68:   upstream_channel_oil_detach(up);
                     69: 
                     70:   /*
                     71:     notice that listnode_delete() can't be moved
                     72:     into pim_upstream_free() because the later is
                     73:     called by list_delete_all_node()
                     74:   */
                     75:   listnode_delete(qpim_upstream_list, up);
                     76: 
                     77:   pim_upstream_free(up);
                     78: }
                     79: 
                     80: static void send_join(struct pim_upstream *up)
                     81: {
                     82:   zassert(up->join_state == PIM_UPSTREAM_JOINED);
                     83: 
                     84:   
                     85:   if (PIM_DEBUG_PIM_TRACE) {
                     86:     if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) {
                     87:       char src_str[100];
                     88:       char grp_str[100];
                     89:       char rpf_str[100];
                     90:       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                     91:       pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                     92:       pim_inet4_dump("<rpf?>", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str));
                     93:       zlog_warn("%s: can't send join upstream: RPF'(%s,%s)=%s",
                     94:                __PRETTY_FUNCTION__,
                     95:                src_str, grp_str, rpf_str);
                     96:       /* warning only */
                     97:     }
                     98:   }
                     99:   
                    100:   /* send Join(S,G) to the current upstream neighbor */
                    101:   pim_joinprune_send(up->rpf.source_nexthop.interface,
                    102:                     up->rpf.rpf_addr,
                    103:                     up->source_addr,
                    104:                     up->group_addr,
                    105:                     1 /* join */);
                    106: }
                    107: 
                    108: static int on_join_timer(struct thread *t)
                    109: {
                    110:   struct pim_upstream *up;
                    111: 
                    112:   zassert(t);
                    113:   up = THREAD_ARG(t);
                    114:   zassert(up);
                    115: 
                    116:   send_join(up);
                    117: 
                    118:   up->t_join_timer = 0;
                    119:   join_timer_start(up);
                    120: 
                    121:   return 0;
                    122: }
                    123: 
                    124: static void join_timer_start(struct pim_upstream *up)
                    125: {
                    126:   if (PIM_DEBUG_PIM_EVENTS) {
                    127:     char src_str[100];
                    128:     char grp_str[100];
                    129:     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    130:     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    131:     zlog_debug("%s: starting %d sec timer for upstream (S,G)=(%s,%s)",
                    132:               __PRETTY_FUNCTION__,
                    133:               qpim_t_periodic,
                    134:               src_str, grp_str);
                    135:   }
                    136: 
                    137:   zassert(!up->t_join_timer);
                    138: 
                    139:   THREAD_TIMER_ON(master, up->t_join_timer,
                    140:                  on_join_timer,
                    141:                  up, qpim_t_periodic);
                    142: }
                    143: 
                    144: void pim_upstream_join_timer_restart(struct pim_upstream *up)
                    145: {
                    146:   THREAD_OFF(up->t_join_timer);
                    147:   join_timer_start(up);
                    148: }
                    149: 
                    150: static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up,
                    151:                                                 int interval_msec)
                    152: {
                    153:   if (PIM_DEBUG_PIM_EVENTS) {
                    154:     char src_str[100];
                    155:     char grp_str[100];
                    156:     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    157:     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    158:     zlog_debug("%s: restarting %d msec timer for upstream (S,G)=(%s,%s)",
                    159:               __PRETTY_FUNCTION__,
                    160:               interval_msec,
                    161:               src_str, grp_str);
                    162:   }
                    163: 
                    164:   THREAD_OFF(up->t_join_timer);
                    165:   THREAD_TIMER_MSEC_ON(master, up->t_join_timer,
                    166:                       on_join_timer,
                    167:                       up, interval_msec);
                    168: }
                    169: 
                    170: void pim_upstream_join_suppress(struct pim_upstream *up,
                    171:                                struct in_addr rpf_addr,
                    172:                                int holdtime)
                    173: {
                    174:   long t_joinsuppress_msec;
                    175:   long join_timer_remain_msec;
                    176: 
                    177:   t_joinsuppress_msec = MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface),
                    178:                            1000 * holdtime);
                    179: 
                    180:   join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer);
                    181: 
                    182:   if (PIM_DEBUG_PIM_TRACE) {
                    183:     char src_str[100];
                    184:     char grp_str[100];
                    185:     char rpf_str[100];
                    186:     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    187:     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    188:     pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str));
                    189:     zlog_debug("%s %s: detected Join(%s,%s) to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec",
                    190:               __FILE__, __PRETTY_FUNCTION__, 
                    191:               src_str, grp_str,
                    192:               rpf_str,
                    193:               join_timer_remain_msec, t_joinsuppress_msec);
                    194:   }
                    195: 
                    196:   if (join_timer_remain_msec < t_joinsuppress_msec) {
                    197:     if (PIM_DEBUG_PIM_TRACE) {
                    198:       char src_str[100];
                    199:       char grp_str[100];
                    200:       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    201:       pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    202:       zlog_debug("%s %s: suppressing Join(S,G)=(%s,%s) for %ld msec",
                    203:                 __FILE__, __PRETTY_FUNCTION__, 
                    204:                 src_str, grp_str, t_joinsuppress_msec);
                    205:     }
                    206: 
                    207:     pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec);
                    208:   }
                    209: }
                    210: 
                    211: void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
                    212:                                                    struct pim_upstream *up,
                    213:                                                    struct in_addr rpf_addr)
                    214: {
                    215:   long join_timer_remain_msec;
                    216:   int t_override_msec;
                    217: 
                    218:   join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer);
                    219:   t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface);
                    220: 
                    221:   if (PIM_DEBUG_PIM_TRACE) {
                    222:     char src_str[100];
                    223:     char grp_str[100];
                    224:     char rpf_str[100];
                    225:     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    226:     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    227:     pim_inet4_dump("<rpf?>", rpf_addr, rpf_str, sizeof(rpf_str));
                    228:     zlog_debug("%s: to RPF'(%s,%s)=%s: join_timer=%ld msec t_override=%d msec",
                    229:               debug_label,
                    230:               src_str, grp_str, rpf_str,
                    231:               join_timer_remain_msec, t_override_msec);
                    232:   }
                    233:     
                    234:   if (join_timer_remain_msec > t_override_msec) {
                    235:     if (PIM_DEBUG_PIM_TRACE) {
                    236:       char src_str[100];
                    237:       char grp_str[100];
                    238:       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    239:       pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    240:       zlog_debug("%s: decreasing (S,G)=(%s,%s) join timer to t_override=%d msec",
                    241:                 debug_label,
                    242:                 src_str, grp_str,
                    243:                 t_override_msec);
                    244:     }
                    245: 
                    246:     pim_upstream_join_timer_restart_msec(up, t_override_msec);
                    247:   }
                    248: }
                    249: 
                    250: static void forward_on(struct pim_upstream *up)
                    251: {
                    252:   struct listnode      *ifnode;
                    253:   struct listnode      *ifnextnode;
                    254:   struct listnode      *chnode;
                    255:   struct listnode      *chnextnode;
                    256:   struct interface     *ifp;
                    257:   struct pim_interface *pim_ifp;
                    258:   struct pim_ifchannel *ch;
                    259: 
                    260:   /* scan all interfaces */
                    261:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    262:     pim_ifp = ifp->info;
                    263:     if (!pim_ifp)
                    264:       continue;
                    265: 
                    266:     /* scan per-interface (S,G) state */
                    267:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    268: 
                    269:       if (ch->upstream != up)
                    270:        continue;
                    271: 
                    272:       if (pim_macro_chisin_oiflist(ch))
                    273:        pim_forward_start(ch);
                    274: 
                    275:     } /* scan iface channel list */
                    276:   } /* scan iflist */
                    277: }
                    278: 
                    279: static void forward_off(struct pim_upstream *up)
                    280: {
                    281:   struct listnode      *ifnode;
                    282:   struct listnode      *ifnextnode;
                    283:   struct listnode      *chnode;
                    284:   struct listnode      *chnextnode;
                    285:   struct interface     *ifp;
                    286:   struct pim_interface *pim_ifp;
                    287:   struct pim_ifchannel *ch;
                    288: 
                    289:   /* scan all interfaces */
                    290:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    291:     pim_ifp = ifp->info;
                    292:     if (!pim_ifp)
                    293:       continue;
                    294: 
                    295:     /* scan per-interface (S,G) state */
                    296:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    297: 
                    298:       if (ch->upstream != up)
                    299:        continue;
                    300: 
                    301:       pim_forward_stop(ch);
                    302: 
                    303:     } /* scan iface channel list */
                    304:   } /* scan iflist */
                    305: }
                    306: 
                    307: static void pim_upstream_switch(struct pim_upstream *up,
                    308:                                enum pim_upstream_state new_state)
                    309: {
                    310:   enum pim_upstream_state old_state = up->join_state;
                    311: 
                    312:   zassert(old_state != new_state);
                    313:   
                    314:   up->join_state       = new_state;
                    315:   up->state_transition = pim_time_monotonic_sec();
                    316: 
                    317:   if (PIM_DEBUG_PIM_EVENTS) {
                    318:     char src_str[100];
                    319:     char grp_str[100];
                    320:     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    321:     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    322:     zlog_debug("%s: PIM_UPSTREAM_%s: (S,G)=(%s,%s)",
                    323:               __PRETTY_FUNCTION__,
                    324:               ((new_state == PIM_UPSTREAM_JOINED) ? "JOINED" : "NOTJOINED"),
                    325:               src_str, grp_str);
                    326:   }
                    327: 
                    328:   pim_upstream_update_assert_tracking_desired(up);
                    329: 
                    330:   if (new_state == PIM_UPSTREAM_JOINED) {
                    331:     forward_on(up);
                    332:     send_join(up);
                    333:     join_timer_start(up);
                    334:   }
                    335:   else {
                    336:     forward_off(up);
                    337:     pim_joinprune_send(up->rpf.source_nexthop.interface,
                    338:                       up->rpf.rpf_addr,
                    339:                       up->source_addr,
                    340:                       up->group_addr,
                    341:                       0 /* prune */);
                    342:     zassert(up->t_join_timer);
                    343:     THREAD_OFF(up->t_join_timer);
                    344:   }
                    345: 
                    346: }
                    347: 
                    348: static struct pim_upstream *pim_upstream_new(struct in_addr source_addr,
                    349:                                             struct in_addr group_addr)
                    350: {
                    351:   struct pim_upstream *up;
                    352:   enum pim_rpf_result rpf_result;
                    353: 
                    354:   up = XMALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up));
                    355:   if (!up) {
                    356:     zlog_err("%s: PIM XMALLOC(%zu) failure",
                    357:             __PRETTY_FUNCTION__, sizeof(*up));
                    358:     return 0;
                    359:   }
                    360:   
                    361:   up->source_addr                = source_addr;
                    362:   up->group_addr                 = group_addr;
                    363:   up->flags                      = 0;
                    364:   up->ref_count                  = 1;
                    365:   up->t_join_timer               = 0;
                    366:   up->join_state                 = 0;
                    367:   up->state_transition           = pim_time_monotonic_sec();
                    368:   up->channel_oil                = 0;
                    369: 
                    370:   up->rpf.source_nexthop.interface                = 0;
                    371:   up->rpf.source_nexthop.mrib_nexthop_addr.s_addr = PIM_NET_INADDR_ANY;
                    372:   up->rpf.source_nexthop.mrib_metric_preference   = qpim_infinite_assert_metric.metric_preference;
                    373:   up->rpf.source_nexthop.mrib_route_metric        = qpim_infinite_assert_metric.route_metric;
                    374:   up->rpf.rpf_addr.s_addr                         = PIM_NET_INADDR_ANY;
                    375: 
                    376:   rpf_result = pim_rpf_update(up, 0);
                    377:   if (rpf_result == PIM_RPF_FAILURE) {
                    378:     XFREE(MTYPE_PIM_UPSTREAM, up);
                    379:     return NULL;
                    380:   }
                    381: 
                    382:   listnode_add(qpim_upstream_list, up);
                    383: 
                    384:   return up;
                    385: }
                    386: 
                    387: struct pim_upstream *pim_upstream_find(struct in_addr source_addr,
                    388:                                       struct in_addr group_addr)
                    389: {
                    390:   struct listnode     *up_node;
                    391:   struct pim_upstream *up;
                    392: 
                    393:   for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) {
                    394:     if (
                    395:        (source_addr.s_addr == up->source_addr.s_addr) &&
                    396:        (group_addr.s_addr == up->group_addr.s_addr)
                    397:        ) {
                    398:       return up;
                    399:     }
                    400:   }
                    401: 
                    402:   return 0;
                    403: }
                    404: 
                    405: struct pim_upstream *pim_upstream_add(struct in_addr source_addr,
                    406:                                      struct in_addr group_addr)
                    407: {
                    408:   struct pim_upstream *up;
                    409: 
                    410:   up = pim_upstream_find(source_addr, group_addr);
                    411:   if (up) {
                    412:     ++up->ref_count;
                    413:   }
                    414:   else {
                    415:     up = pim_upstream_new(source_addr, group_addr);
                    416:   }
                    417: 
                    418:   return up;
                    419: }
                    420: 
                    421: void pim_upstream_del(struct pim_upstream *up)
                    422: {
                    423:   --up->ref_count;
                    424: 
                    425:   if (up->ref_count < 1) {
                    426:     pim_upstream_delete(up);
                    427:   }
                    428: }
                    429: 
                    430: /*
                    431:   Evaluate JoinDesired(S,G):
                    432: 
                    433:   JoinDesired(S,G) is true if there is a downstream (S,G) interface I
                    434:   in the set:
                    435: 
                    436:   inherited_olist(S,G) =
                    437:   joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G)
                    438: 
                    439:   JoinDesired(S,G) may be affected by changes in the following:
                    440: 
                    441:   pim_ifp->primary_address
                    442:   pim_ifp->pim_dr_addr
                    443:   ch->ifassert_winner_metric
                    444:   ch->ifassert_winner
                    445:   ch->local_ifmembership 
                    446:   ch->ifjoin_state
                    447:   ch->upstream->rpf.source_nexthop.mrib_metric_preference
                    448:   ch->upstream->rpf.source_nexthop.mrib_route_metric
                    449:   ch->upstream->rpf.source_nexthop.interface
                    450: 
                    451:   See also pim_upstream_update_join_desired() below.
                    452:  */
                    453: int pim_upstream_evaluate_join_desired(struct pim_upstream *up)
                    454: {
                    455:   struct listnode      *ifnode;
                    456:   struct listnode      *ifnextnode;
                    457:   struct listnode      *chnode;
                    458:   struct listnode      *chnextnode;
                    459:   struct interface     *ifp;
                    460:   struct pim_interface *pim_ifp;
                    461:   struct pim_ifchannel *ch;
                    462: 
                    463:   /* scan all interfaces */
                    464:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    465:     pim_ifp = ifp->info;
                    466:     if (!pim_ifp)
                    467:       continue;
                    468: 
                    469:     /* scan per-interface (S,G) state */
                    470:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    471:       if (ch->upstream != up)
                    472:        continue;
                    473: 
                    474:       if (pim_macro_ch_lost_assert(ch))
                    475:        continue; /* keep searching */
                    476: 
                    477:       if (pim_macro_chisin_joins_or_include(ch))
                    478:        return 1; /* true */
                    479:     } /* scan iface channel list */
                    480:   } /* scan iflist */
                    481: 
                    482:   return 0; /* false */
                    483: }
                    484: 
                    485: /*
                    486:   See also pim_upstream_evaluate_join_desired() above.
                    487: */
                    488: void pim_upstream_update_join_desired(struct pim_upstream *up)
                    489: {
                    490:   int was_join_desired; /* boolean */
                    491:   int is_join_desired; /* boolean */
                    492: 
                    493:   was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags);
                    494: 
                    495:   is_join_desired = pim_upstream_evaluate_join_desired(up);
                    496:   if (is_join_desired)
                    497:     PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags);
                    498:   else
                    499:     PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags);
                    500: 
                    501:   /* switched from false to true */
                    502:   if (is_join_desired && !was_join_desired) {
                    503:     zassert(up->join_state == PIM_UPSTREAM_NOTJOINED);
                    504:     pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
                    505:     return;
                    506:   }
                    507:       
                    508:   /* switched from true to false */
                    509:   if (!is_join_desired && was_join_desired) {
                    510:     zassert(up->join_state == PIM_UPSTREAM_JOINED);
                    511:     pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED);
                    512:     return;
                    513:   }
                    514: }
                    515: 
                    516: /*
                    517:   RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages
                    518:   Transitions from Joined State
                    519:   RPF'(S,G) GenID changes
                    520: 
                    521:   The upstream (S,G) state machine remains in Joined state.  If the
                    522:   Join Timer is set to expire in more than t_override seconds, reset
                    523:   it so that it expires after t_override seconds.
                    524: */
                    525: void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr)
                    526: {
                    527:   struct listnode     *up_node;
                    528:   struct listnode     *up_nextnode;
                    529:   struct pim_upstream *up;
                    530: 
                    531:   /*
                    532:     Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
                    533:   */
                    534:   for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) {
                    535: 
                    536:     if (PIM_DEBUG_PIM_TRACE) {
                    537:       char neigh_str[100];
                    538:       char src_str[100];
                    539:       char grp_str[100];
                    540:       char rpf_addr_str[100];
                    541:       pim_inet4_dump("<neigh?>", neigh_addr, neigh_str, sizeof(neigh_str));
                    542:       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
                    543:       pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
                    544:       pim_inet4_dump("<rpf?>", up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
                    545:       zlog_debug("%s: matching neigh=%s against upstream (S,G)=(%s,%s) joined=%d rpf_addr=%s",
                    546:                 __PRETTY_FUNCTION__,
                    547:                 neigh_str, src_str, grp_str,
                    548:                 up->join_state == PIM_UPSTREAM_JOINED,
                    549:                 rpf_addr_str);
                    550:     }
                    551: 
                    552:     /* consider only (S,G) upstream in Joined state */
                    553:     if (up->join_state != PIM_UPSTREAM_JOINED)
                    554:       continue;
                    555: 
                    556:     /* match RPF'(S,G)=neigh_addr */
                    557:     if (up->rpf.rpf_addr.s_addr != neigh_addr.s_addr)
                    558:       continue;
                    559: 
                    560:     pim_upstream_join_timer_decrease_to_t_override("RPF'(S,G) GenID change",
                    561:                                                   up, neigh_addr);
                    562:   }
                    563: }
                    564: 
                    565: 
                    566: void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
                    567:                                        struct interface *old_rpf_ifp)
                    568: {
                    569:   struct listnode  *ifnode;
                    570:   struct listnode  *ifnextnode;
                    571:   struct interface *ifp;
                    572: 
                    573:   /* scan all interfaces */
                    574:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    575:     struct listnode      *chnode;
                    576:     struct listnode      *chnextnode;
                    577:     struct pim_ifchannel *ch;
                    578:     struct pim_interface *pim_ifp;
                    579: 
                    580:     pim_ifp = ifp->info;
                    581:     if (!pim_ifp)
                    582:       continue;
                    583: 
                    584:     /* search all ifchannels */
                    585:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    586:       if (ch->upstream != up)
                    587:        continue;
                    588: 
                    589:       if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
                    590:        if (
                    591:            /* RPF_interface(S) was NOT I */
                    592:            (old_rpf_ifp == ch->interface)
                    593:            &&
                    594:            /* RPF_interface(S) stopped being I */
                    595:            (ch->upstream->rpf.source_nexthop.interface != ch->interface)
                    596:            ) {
                    597:          assert_action_a5(ch);
                    598:        }
                    599:       } /* PIM_IFASSERT_I_AM_LOSER */
                    600: 
                    601:       pim_ifchannel_update_assert_tracking_desired(ch);
                    602:     }
                    603:   }
                    604: }
                    605: 
                    606: void pim_upstream_update_could_assert(struct pim_upstream *up)
                    607: {
                    608:   struct listnode      *ifnode;
                    609:   struct listnode      *ifnextnode;
                    610:   struct listnode      *chnode;
                    611:   struct listnode      *chnextnode;
                    612:   struct interface     *ifp;
                    613:   struct pim_interface *pim_ifp;
                    614:   struct pim_ifchannel *ch;
                    615: 
                    616:   /* scan all interfaces */
                    617:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    618:     pim_ifp = ifp->info;
                    619:     if (!pim_ifp)
                    620:       continue;
                    621: 
                    622:     /* scan per-interface (S,G) state */
                    623:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    624: 
                    625:       if (ch->upstream != up)
                    626:        continue;
                    627: 
                    628:       pim_ifchannel_update_could_assert(ch);
                    629: 
                    630:     } /* scan iface channel list */
                    631:   } /* scan iflist */
                    632: }
                    633: 
                    634: void pim_upstream_update_my_assert_metric(struct pim_upstream *up)
                    635: {
                    636:   struct listnode      *ifnode;
                    637:   struct listnode      *ifnextnode;
                    638:   struct listnode      *chnode;
                    639:   struct listnode      *chnextnode;
                    640:   struct interface     *ifp;
                    641:   struct pim_interface *pim_ifp;
                    642:   struct pim_ifchannel *ch;
                    643: 
                    644:   /* scan all interfaces */
                    645:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    646:     pim_ifp = ifp->info;
                    647:     if (!pim_ifp)
                    648:       continue;
                    649: 
                    650:     /* scan per-interface (S,G) state */
                    651:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    652: 
                    653:       if (ch->upstream != up)
                    654:        continue;
                    655: 
                    656:       pim_ifchannel_update_my_assert_metric(ch);
                    657: 
                    658:     } /* scan iface channel list */
                    659:   } /* scan iflist */
                    660: }
                    661: 
                    662: static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)
                    663: {
                    664:   struct listnode      *ifnode;
                    665:   struct listnode      *ifnextnode;
                    666:   struct listnode      *chnode;
                    667:   struct listnode      *chnextnode;
                    668:   struct interface     *ifp;
                    669:   struct pim_interface *pim_ifp;
                    670:   struct pim_ifchannel *ch;
                    671: 
                    672:   /* scan all interfaces */
                    673:   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
                    674:     pim_ifp = ifp->info;
                    675:     if (!pim_ifp)
                    676:       continue;
                    677: 
                    678:     /* scan per-interface (S,G) state */
                    679:     for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, chnode, chnextnode, ch)) {
                    680: 
                    681:       if (ch->upstream != up)
                    682:        continue;
                    683: 
                    684:       pim_ifchannel_update_assert_tracking_desired(ch);
                    685: 
                    686:     } /* scan iface channel list */
                    687:   } /* scan iflist */
                    688: }

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