]> git.proxmox.com Git - mirror_frr.git/commitdiff
pimd: PIM BSM processing, grp2rp mapping timer expiry
authorsaravanank <saravanank@vmware.com>
Fri, 3 May 2019 14:26:37 +0000 (07:26 -0700)
committersaravanank <saravanank@vmware.com>
Wed, 15 May 2019 04:40:50 +0000 (21:40 -0700)
DS Overview:
Bootstrap RP table has grp node.
scope --> rp table --> grp node1 --> rp list --> rp nodes(g2rp timer)
             |
              -------> grp node2 --> rp list --> rp nodes(g2rp timer)

When grp2rp mapping expires, following has to be done.
1. delete the rp node from the active bs-rp list in the list
2. calculate the elapsed time for other rp nodes in the list
3. delete those nodes having more elapse time than their hold time
4. If the list is not empty and current rp src is not static
   rp change with new rp(head) & start g2rp timer with value holdtime - elapse
5. If the list is empty and current rp src for the grp is not static
   delete the rp
6. If the list is not empty and current rp is static, just start the
   g2rp timer with value holdtime - elapse
7. If list is empty and pending list is empty, delete grp node.

Note: g2rp timer will be run only on elected RP node for optimization.
      when it expires, other node are update with elapse time.
      This list is sorted insuch way that elected RP is the HEAD of list

Signed-off-by: Saravanan K <saravanank@vmware.com>
pimd/pim_bsm.c

index e316bc738da397accc95133ee55842a9efc723ad..66744e3342421a888b6b94cb7857489e8feef225 100644 (file)
@@ -64,6 +64,18 @@ static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
        XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node);
 }
 
+static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
+{
+       struct route_node *rn;
+
+       rn = route_node_lookup(rt, grp);
+       if (rn) {
+               rn->info = NULL;
+               route_unlock_node(rn);
+               route_unlock_node(rn);
+       }
+}
+
 static void pim_bsm_node_free(struct bsm_info *bsm)
 {
        if (bsm->bsm)
@@ -136,8 +148,83 @@ void pim_bsm_proc_free(struct pim_instance *pim)
                route_table_finish(pim->global_scope.bsrp_table);
 }
 
+static bool is_hold_time_elapsed(void *data)
+{
+       struct bsm_rpinfo *bsrp;
+
+       bsrp = data;
+
+       if (bsrp->elapse_time < bsrp->rp_holdtime)
+               return false;
+       else
+               return true;
+}
+
 static int pim_on_g2rp_timer(struct thread *t)
 {
+       struct bsm_rpinfo *bsrp;
+       struct bsm_rpinfo *bsrp_node;
+       struct bsgrp_node *bsgrp_node;
+       struct listnode *bsrp_ln;
+       struct pim_instance *pim;
+       struct rp_info *rp_info;
+       struct route_node *rn;
+       uint16_t elapse;
+       struct in_addr bsrp_addr;
+
+       bsrp = THREAD_ARG(t);
+       THREAD_OFF(bsrp->g2rp_timer);
+       bsgrp_node = bsrp->bsgrp_node;
+
+       /* elapse time is the hold time of expired node */
+       elapse = bsrp->rp_holdtime;
+       bsrp_addr = bsrp->rp_address;
+
+       /* update elapse for all bsrp nodes */
+       for (ALL_LIST_ELEMENTS_RO(bsgrp_node->bsrp_list, bsrp_ln, bsrp_node))
+               bsrp_node->elapse_time += elapse;
+
+       /* remove the expired nodes from the list */
+       list_filter_out_nodes(bsgrp_node->bsrp_list, is_hold_time_elapsed);
+
+       /* Get the next elected rp node */
+       bsrp = listnode_head(bsgrp_node->bsrp_list);
+       pim = bsgrp_node->scope->pim;
+       rn = route_node_lookup(pim->rp_table, &bsgrp_node->group);
+
+       if (!rn) {
+               zlog_warn("%s: Route node doesn't exist", __PRETTY_FUNCTION__);
+               return 0;
+       }
+
+       rp_info = (struct rp_info *)rn->info;
+
+       if (!rp_info) {
+               route_unlock_node(rn);
+               return 0;
+       }
+
+       if (rp_info->rp_src != RP_SRC_STATIC) {
+               /* If new rp available, change it else delete the existing */
+               if (bsrp) {
+                       bsrp_addr = bsrp->rp_address;
+                       pim_g2rp_timer_start(
+                               bsrp, (bsrp->rp_holdtime - bsrp->elapse_time));
+                       pim_rp_change(pim, bsrp_addr, bsgrp_node->group,
+                                     RP_SRC_BSR);
+               } else {
+                       pim_rp_del(pim, bsrp_addr, bsgrp_node->group, NULL,
+                                  RP_SRC_BSR);
+               }
+       }
+
+       if ((!bsgrp_node->bsrp_list->count)
+           && (!bsgrp_node->partial_bsrp_list->count)) {
+               pim_free_bsgrp_node(pim->global_scope.bsrp_table,
+                                   &bsgrp_node->group);
+               pim_free_bsgrp_data(bsgrp_node);
+       }
+
        return 0;
 }