static void pim_addr_change(struct interface *ifp)
{
  struct pim_interface *pim_ifp;

  pim_ifp = ifp->info;
  zassert(pim_ifp);

  pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- Done TODO T30 */
  pim_if_update_join_desired(pim_ifp); /* depends on DR */
  pim_if_update_could_assert(ifp); /* depends on DR */
  pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
  pim_if_update_assert_tracking_desired(ifp); /* depends on DR, join_desired */

  /*
    RFC 4601: 4.3.1.  Sending Hello Messages

    1) Before an interface goes down or changes primary IP address, a
    Hello message with a zero HoldTime should be sent immediately
    (with the old IP address if the IP address changed).
    -- FIXME See CAVEAT C13

    2) After an interface has changed its IP address, it MUST send a
    Hello message with its new IP address.
    -- DONE below

    3) If an interface changes one of its secondary IP addresses, a
    Hello message with an updated Address_List option and a non-zero
    HoldTime should be sent immediately.
    -- FIXME See TODO T31
   */
  pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */
  if (pim_ifp->pim_sock_fd < 0)
    return;
  pim_hello_restart_now(ifp);         /* send hello and restart timer */
}
Ejemplo n.º 2
0
/*
  RFC 4601: 4.3.2.  DR Election

  A router's idea of the current DR on an interface can change when a
  PIM Hello message is received, when a neighbor times out, or when a
  router's own DR Priority changes.
 */
int pim_if_dr_election(struct interface *ifp)
{
  struct pim_interface *pim_ifp = ifp->info;
  struct in_addr old_dr_addr;

  ++pim_ifp->pim_dr_election_count;

  old_dr_addr = pim_ifp->pim_dr_addr;

  if (pim_ifp->pim_dr_num_nondrpri_neighbors) {
    dr_election_by_addr(ifp);
  }
  else {
    dr_election_by_pri(ifp);
  }

  /* DR changed ? */
  if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {

    if (PIM_DEBUG_PIM_EVENTS) {
      char dr_old_str[100];
      char dr_new_str[100];
      pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str));
      pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str));
      zlog_debug("%s: DR was %s now is %s on interface %s",
		 __PRETTY_FUNCTION__,
		 dr_old_str, dr_new_str, ifp->name);
    }

    pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */
    ++pim_ifp->pim_dr_election_changes; 
    pim_if_update_join_desired(pim_ifp);
    pim_if_update_could_assert(ifp);
    pim_if_update_assert_tracking_desired(ifp);
    return 1;
  }

  return 0;
}