diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/zebra_rib.c | 134 | 
1 files changed, 70 insertions, 64 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index cc63dba0..99b5296b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1189,21 +1189,30 @@ end:      zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);  } -/* Take a list of route_node structs and return 1, if there was a record picked from - * it and processed by rib_process(). Don't process more, than one RN record; operate - * only in the specified sub-queue. +/* Take a list of route_node structs and return 1, if there was a record + * picked from it and processed by rib_process(). Don't process more,  + * than one RN record; operate only in the specified sub-queue.   */  static unsigned int  process_subq (struct list * subq, u_char qindex)  { -  struct listnode *lnode; +  struct listnode *lnode  = listhead (subq);    struct route_node *rnode; -  if (!(lnode = listhead (subq))) + +  if (!lnode)      return 0; +    rnode = listgetdata (lnode);    rib_process (rnode); +    if (rnode->info) /* The first RIB record is holding the flags bitmask. */      UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); +  else +    { +      zlog_debug ("%s: called for route_node (%p, %d) with no ribs", +                  __func__, rnode, rnode->lock); +      zlog_backtrace(LOG_DEBUG); +    }    route_unlock_node (rnode);    list_delete_node (subq, lnode);    return 1; @@ -1217,66 +1226,66 @@ static wq_item_status  meta_queue_process (struct work_queue *dummy, void *data)  {    struct meta_queue * mq = data; -  u_char i; +  unsigned i; +    for (i = 0; i < MQ_SIZE; i++)      if (process_subq (mq->subq[i], i)) -    { -      mq->size--; -      break; -    } +      { +	mq->size--; +	break; +      }    return mq->size ? WQ_REQUEUE : WQ_SUCCESS;  } -/* Look into the RN and queue it into one or more priority queues, increasing the size - * for each data push done. +/* Map from rib types to queue type (priority) in meta queue */ +static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = { +  [ZEBRA_ROUTE_SYSTEM]  = 4, +  [ZEBRA_ROUTE_KERNEL]  = 0, +  [ZEBRA_ROUTE_CONNECT] = 0, +  [ZEBRA_ROUTE_STATIC]  = 1, +  [ZEBRA_ROUTE_RIP]     = 2, +  [ZEBRA_ROUTE_RIPNG]   = 2, +  [ZEBRA_ROUTE_OSPF]    = 2, +  [ZEBRA_ROUTE_OSPF6]   = 2, +  [ZEBRA_ROUTE_ISIS]    = 2, +  [ZEBRA_ROUTE_BGP]     = 3, +  [ZEBRA_ROUTE_HSLS]    = 4, +}; + +/* Look into the RN and queue it into one or more priority queues, + * increasing the size for each data push done.   */  static void  rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)  { -  u_char qindex;    struct rib *rib;    char buf[INET6_ADDRSTRLEN]; +    if (IS_ZEBRA_DEBUG_RIB_Q)      inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); +    for (rib = rn->info; rib; rib = rib->next) -  { -    switch (rib->type) -    { -      case ZEBRA_ROUTE_KERNEL: -      case ZEBRA_ROUTE_CONNECT: -        qindex = 0; -        break; -      case ZEBRA_ROUTE_STATIC: -        qindex = 1; -        break; -      case ZEBRA_ROUTE_RIP: -      case ZEBRA_ROUTE_RIPNG: -      case ZEBRA_ROUTE_OSPF: -      case ZEBRA_ROUTE_OSPF6: -      case ZEBRA_ROUTE_ISIS: -        qindex = 2; -        break; -      case ZEBRA_ROUTE_BGP: -        qindex = 3; -        break; -      default: -        qindex = 4; -        break; -    } -    /* Invariant: at this point we always have rn->info set. */ -    if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)))      { +      u_char qindex = meta_queue_map[rib->type]; + +      /* Invariant: at this point we always have rn->info set. */ +      if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex))) +	{ +	  if (IS_ZEBRA_DEBUG_RIB_Q) +	    zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", +			__func__, buf, rn->p.prefixlen, rn, qindex); +	  continue; +	} + +      SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); +      listnode_add (mq->subq[qindex], rn); +      route_lock_node (rn); +      mq->size++; +        if (IS_ZEBRA_DEBUG_RIB_Q) -        zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex); -      continue; -    } -    SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); -    listnode_add (mq->subq[qindex], rn); -    route_lock_node (rn); -    mq->size++; -    if (IS_ZEBRA_DEBUG_RIB_Q) -      zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex); -  } +	zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u", +		    __func__, buf, rn->p.prefixlen, rn, qindex); +    }  }  /* Add route_node to work queue and schedule processing */ @@ -1328,27 +1337,24 @@ rib_queue_add (struct zebra_t *zebra, struct route_node *rn)    return;  } -/* Create new meta queue. A destructor function doesn't seem to be necessary here. */ +/* Create new meta queue. +   A destructor function doesn't seem to be necessary here. + */  static struct meta_queue *  meta_queue_new (void)  {    struct meta_queue *new; -  unsigned i, failed = 0; +  unsigned i; + +  new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue)); +  assert(new); -  if ((new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue))) == NULL) -    return NULL;    for (i = 0; i < MQ_SIZE; i++) -    if ((new->subq[i] = list_new ()) == NULL) -      failed = 1; -  if (failed) -  { -    for (i = 0; i < MQ_SIZE; i++) -      if (new->subq[i]) -        list_delete (new->subq[i]); -    XFREE (MTYPE_WORK_QUEUE, new); -    return NULL; -  } -  new->size = 0; +    { +      new->subq[i] = list_new (); +      assert(new->subq[i]); +    } +    return new;  }  | 
