Example #1
0
static void scan_upstream_rpf_cache()
{
  struct listnode     *up_node;
  struct listnode     *up_nextnode;
  struct pim_upstream *up;

  for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) {
    struct in_addr      old_rpf_addr;
    enum pim_rpf_result rpf_result;

    rpf_result = pim_rpf_update(up, &old_rpf_addr);
    if (rpf_result == PIM_RPF_FAILURE)
      continue;

    if (rpf_result == PIM_RPF_CHANGED) {
      
      if (up->join_state == PIM_UPSTREAM_JOINED) {
	
	/*
	  RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Messages
	  
	  Transitions from Joined State
	  
	  RPF'(S,G) changes not due to an Assert
	  
	  The upstream (S,G) state machine remains in Joined
	  state. Send Join(S,G) to the new upstream neighbor, which is
	  the new value of RPF'(S,G).  Send Prune(S,G) to the old
	  upstream neighbor, which is the old value of RPF'(S,G).  Set
	  the Join Timer (JT) to expire after t_periodic seconds.
	*/

    
	/* send Prune(S,G) to the old upstream neighbor */
	pim_joinprune_send(up->rpf.source_nexthop.interface,
			   old_rpf_addr,
			   up->source_addr,
			   up->group_addr,
			   0 /* prune */);
	
	/* send Join(S,G) to the current upstream neighbor */
	pim_joinprune_send(up->rpf.source_nexthop.interface,
			   up->rpf.rpf_addr,
			   up->source_addr,
			   up->group_addr,
			   1 /* join */);

	pim_upstream_join_timer_restart(up);
      } /* up->join_state == PIM_UPSTREAM_JOINED */

      /* FIXME can join_desired actually be changed by pim_rpf_update()
	 returning PIM_RPF_CHANGED ? */
      pim_upstream_update_join_desired(up);

    } /* PIM_RPF_CHANGED */

  } /* for (qpim_upstream_list) */
  
}
static void send_join(struct pim_upstream *up)
{
  zassert(up->join_state == PIM_UPSTREAM_JOINED);

  
  if (PIM_DEBUG_PIM_TRACE) {
    if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) {
      char src_str[100];
      char grp_str[100];
      char rpf_str[100];
      pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
      pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
      pim_inet4_dump("<rpf?>", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str));
      zlog_warn("%s: can't send join upstream: RPF'(%s,%s)=%s",
		__PRETTY_FUNCTION__,
		src_str, grp_str, rpf_str);
      /* warning only */
    }
  }
  
  /* send Join(S,G) to the current upstream neighbor */
  pim_joinprune_send(up->rpf.source_nexthop.interface,
  		     up->rpf.rpf_addr,
		     up->source_addr,
		     up->group_addr,
		     1 /* join */);
}
static void pim_upstream_switch(struct pim_upstream *up,
				enum pim_upstream_state new_state)
{
  enum pim_upstream_state old_state = up->join_state;

  zassert(old_state != new_state);
  
  up->join_state       = new_state;
  up->state_transition = pim_time_monotonic_sec();

  if (PIM_DEBUG_PIM_EVENTS) {
    char src_str[100];
    char grp_str[100];
    pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
    pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
    zlog_debug("%s: PIM_UPSTREAM_%s: (S,G)=(%s,%s)",
	       __PRETTY_FUNCTION__,
	       ((new_state == PIM_UPSTREAM_JOINED) ? "JOINED" : "NOTJOINED"),
	       src_str, grp_str);
  }

  pim_upstream_update_assert_tracking_desired(up);

  if (new_state == PIM_UPSTREAM_JOINED) {
    forward_on(up);
    send_join(up);
    join_timer_start(up);
  }
  else {
    forward_off(up);
    pim_joinprune_send(up->rpf.source_nexthop.interface,
		       up->rpf.rpf_addr,
		       up->source_addr,
		       up->group_addr,
		       0 /* prune */);
    zassert(up->t_join_timer);
    THREAD_OFF(up->t_join_timer);
  }

}