int
ospf6_flood_interface_mdr (struct ospf6_neighbor *from,
                           struct ospf6_lsa *lsa, struct ospf6_interface *oi)
{
  struct listnode *node, *nnode;
  struct ospf6_neighbor *on;
  struct ospf6_lsa *req;
  int retrans_added = 0;
  int is_debug = 0;
  struct list *flood_neighbors = list_new ();
  bool flood_lsa = true;

  if (IS_OSPF6_DEBUG_FLOODING ||
      IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
    {
      is_debug++;
      zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name);
    }

  /* (1) For each neighbor */
  for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
    {
      if (is_debug)
        zlog_debug ("To neighbor %s", on->name);

      /* (a) if neighbor state < Exchange, examin next */
      // Consider adjacent and (backup) dependent neighbors.
      // Require all bidirectional neighbors to be covered
      if (on->state < OSPF6_NEIGHBOR_TWOWAY)
        {
          if (is_debug)
            zlog_debug ("Neighbor state less than TwoWay, next neighbor");
          continue;
        }

      if (on->state > OSPF6_NEIGHBOR_TWOWAY &&
	  on->state < OSPF6_NEIGHBOR_FULL && !need_adjacency (on))
	{
	  if (is_debug)
	    zlog_debug ("No longer need adjacency with neighbor %s: "
			"scheduling AdjOK?", on->name);
	  ospf6_neighbor_schedule_adjok (on);
	  continue;
	}

      /* (b) if neighbor not yet Full, check request-list */
      if (on->state >= OSPF6_NEIGHBOR_EXCHANGE &&
          on->state != OSPF6_NEIGHBOR_FULL)
        {
          if (is_debug)
            zlog_debug ("Neighbor not yet Full");

          req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
                                   lsa->header->adv_router, on->request_list);
          if (req == NULL)
            {
              if (is_debug)
                zlog_debug ("Not on request-list for this neighbor");
              /* fall through */
            }
          else
            {
              /* If new LSA less recent, examin next neighbor */
              if (ospf6_lsa_compare (lsa, req) > 0)
                {
                  if (is_debug)
                    zlog_debug ("Requesting is newer, next neighbor");
                  continue;
                }

              /* If the same instance, delete from request-list and
                 examin next neighbor */
              if (ospf6_lsa_compare (lsa, req) == 0)
                {
                  if (is_debug)
                    zlog_debug
                      ("Requesting the same, remove it, next neighbor");
                  ospf6_lsdb_remove (req, on->request_list);
                  continue;
                }

              /* If the new LSA is more recent, delete from request-list */
              if (ospf6_lsa_compare (lsa, req) < 0)
                {
                  if (is_debug)
                    zlog_debug ("Received is newer, remove requesting");
                  ospf6_lsdb_remove (req, on->request_list);
                  /* fall through */
                }
            }
        }

      /* (c) If the new LSA was received from this neighbor,
         examin next neighbor */
      if (from == on)
        {
          if (is_debug)
            zlog_debug ("LSA was received from neighbor %s, next neighbor",
			on->name);
          continue;
        }

      //Ogierv3 Section 6 Par 3
      /* At this point, we are not positive that the neighbor has
         an up-to-date instance of this new LSA */
      /* However, in the MANET case, we need to:
         i) check whether neighbor sent a multicast ACK for it already
         ii) whether I am an active relay for this originator */
      /* Has LSA been acked previously with multicast ack? */
      if (ospf6_mdr_neighbor_has_acked (on, lsa))
        {                       //Don't add LSA to neighbor's retransmission list
          if (is_debug)
            zlog_debug ("Existing multicast ACK from neighbor %s found "
			"for LSA, next neighbor", on->name);
          continue;             // examine next neighbor: neighbor already acked
        }
      /* Here, checking for coverage of this neighbor on the sender's RNL.
         If not present, I add this to the flood_neighbors list.
         If LSA was received as a unicast, however, can't assume that
         neighbor "on" was covered by the transmission, so still need to
         add to flood_neighbors regardless of from->rnl */
      if (from)
        {
          if (!from->mdr.Report2Hop ||
              (!CHECK_FLAG (lsa->flag, OSPF6_LSA_RECVMCAST)) ||
              !ospf6_mdr_lookup_neighbor (from->mdr.rnl, on->router_id))
            {
              listnode_add (flood_neighbors, on);
            }
        }

      // Retransmit only to adjacent neighbors.
      if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
        continue;

      /* (d) add retrans-list, schedule retransmission */
      if (is_debug)
        zlog_debug ("Add retrans-list of this neighbor");
      ospf6_increment_retrans_count (lsa);

      quagga_gettime (QUAGGA_CLK_MONOTONIC, &lsa->rxmt_time);
      ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
      on->thread_send_lsupdate =
        ospf6_send_lsupdate_delayed_msec (master,
                                          ospf6_lsupdate_send_neighbor, on,
                                          oi->rxmt_interval * 1000,
                                          on->thread_send_lsupdate);
      retrans_added++;
    }
  /* (2) examin next interface if not added to retrans-list */
  // MDRs can flood an LSA without adding it to the retrans-list
  if (!from && retrans_added == 0)
    {
      /* this LSA is self-originated but there are no adjacent neighbors */
      flood_lsa = false;
      if (is_debug)
        zlog_debug ("Self-originated LSA and no adjacent neighbors");
    }

  //Ogierv3 Section 6 - Remove (3) and (4)

  //Ogierv3 Section 6 - Replace (5)
  //Ogierv3 Forwarding Procedure bullet(a)
  if (from && oi->mdr.mdr_level == OSPF6_MDR)
    {
      //Flood the LSA unless all neighbors are already covered
      if (flood_neighbors->count == 0)
	{
	  flood_lsa = false;
	  if (is_debug)
	    zlog_debug ("All neighbors covered");
	}
      else if (oi->mdr.nonflooding_mdr)
        {
          // Non-flooding MDR acts like a BMDR.
          for (ALL_LIST_ELEMENTS (flood_neighbors, node, nnode, on))
            ospf6_backupwait_lsa_add (lsa, on);
          flood_lsa = false;
	  if (is_debug)
	    zlog_debug ("Router is a non-flooding MDR");
        }
    }
  //Ogierv3 Forwarding Procedure bullet(c)
  else if (from && oi->mdr.mdr_level == OSPF6_BMDR)
Example #2
0
int negotiation_done(struct thread * thread)
{
  struct ospf6_neighbor * on;
  struct ospf6_lsa * lsa;

  on = (struct ospf6_neighbor *) THREAD_ARG(thread);
  assert(on);

  if(on->state != OSPF6_NEIGHBOR_EXSTART)
    return 0;

  if(IS_OSPF6_SIBLING_DEBUG_NEIGHBOR)
    zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name);

  /* clear ls-list */
  ospf6_lsdb_remove_all(on->summary_list);
  ospf6_lsdb_remove_all(on->request_list);

  for(lsa = ospf6_lsdb_head(on->retrans_list); lsa;
      lsa = ospf6_lsdb_next(lsa))
  {
    ospf6_decrement_retrans_count(lsa);
    ospf6_lsdb_remove(lsa, on->retrans_list);
  }

  /* Interface scoped LSAs */
  for(lsa = ospf6_lsdb_head(on->ospf6_if->lsdb); lsa;
      lsa = ospf6_lsdb_next(lsa))
  {
    if (OSPF6_LSA_IS_MAXAGE (lsa))
    {
      ospf6_increment_retrans_count(lsa);
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
    }
    else
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
  }

  /* Area scoped LSAs - no area implemented yet */
//  LIST_FOR_EACH(lsa, struct ospf6_lsa, node, on-> )
//  {

//  }

  /* AS scoped LSAs */
  for(lsa = ospf6_lsdb_head(ospf6->lsdb); lsa;
      lsa = ospf6_lsdb_next(lsa))
  {
    if(OSPF6_LSA_IS_MAXAGE(lsa))
    {
      ospf6_increment_retrans_count(lsa);
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
    }
    else
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
  }
 

  UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
  ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on);

  return 0;
}