static int on_neighbor_timer(struct thread *t) { struct pim_neighbor *neigh; struct interface *ifp; char msg[100]; zassert(t); neigh = THREAD_ARG(t); zassert(neigh); ifp = neigh->interface; if (PIM_DEBUG_PIM_TRACE) { char src_str[100]; pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str)); zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s", neigh->holdtime, src_str, ifp->name); } neigh->t_expire_timer = 0; snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); pim_neighbor_delete(ifp, neigh, msg); /* 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. */ pim_if_dr_election(ifp); // neighbor times out return 0; }
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 */ }
static void update_dr_priority(struct pim_neighbor *neigh, pim_hello_options hello_options, uint32_t dr_priority) { pim_hello_options will_set_pri; /* boolean */ pim_hello_options bit_flip; /* boolean */ pim_hello_options pri_change; /* boolean */ will_set_pri = PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY); bit_flip = ( will_set_pri != PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) ); if (bit_flip) { struct pim_interface *pim_ifp = neigh->interface->info; /* update num. of neighbors without dr_pri */ if (will_set_pri) { --pim_ifp->pim_dr_num_nondrpri_neighbors; } else { ++pim_ifp->pim_dr_num_nondrpri_neighbors; } } pri_change = ( bit_flip || (neigh->dr_priority != dr_priority) ); if (will_set_pri) { neigh->dr_priority = dr_priority; } else { neigh->dr_priority = 0; /* cosmetic unset */ } if (pri_change) { /* 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. */ pim_if_dr_election(neigh->interface); // router's own DR Priority changes } }
struct pim_neighbor *pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, pim_hello_options hello_options, uint16_t holdtime, uint16_t propagation_delay, uint16_t override_interval, uint32_t dr_priority, uint32_t generation_id, struct list *addr_list) { struct pim_interface *pim_ifp; struct pim_neighbor *neigh; neigh = pim_neighbor_new(ifp, source_addr, hello_options, holdtime, propagation_delay, override_interval, dr_priority, generation_id, addr_list); if (!neigh) { return 0; } pim_ifp = ifp->info; zassert(pim_ifp); listnode_add(pim_ifp->pim_neighbor_list, neigh); /* 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. */ pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election... /* RFC 4601: 4.3.1. Sending Hello Messages To allow new or rebooting routers to learn of PIM neighbors quickly, when a Hello message is received from a new neighbor, or a Hello message with a new GenID is received from an existing neighbor, a new Hello message should be sent on this interface after a randomized delay between 0 and Triggered_Hello_Delay. */ pim_hello_restart_triggered(neigh->interface); return neigh; }