pim_neighbor.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. /*
  2. PIM for Quagga
  3. Copyright (C) 2008 Everton da Silva Marques
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; see the file COPYING; if not, write to the
  14. Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  15. MA 02110-1301 USA
  16. $QuaggaId: $Format:%an, %ai, %h$ $
  17. */
  18. #include <zebra.h>
  19. #include "log.h"
  20. #include "prefix.h"
  21. #include "memory.h"
  22. #include "pimd.h"
  23. #include "pim_neighbor.h"
  24. #include "pim_time.h"
  25. #include "pim_str.h"
  26. #include "pim_iface.h"
  27. #include "pim_pim.h"
  28. #include "pim_upstream.h"
  29. #include "pim_ifchannel.h"
  30. static void dr_election_by_addr(struct interface *ifp)
  31. {
  32. struct pim_interface *pim_ifp;
  33. struct listnode *node;
  34. struct pim_neighbor *neigh;
  35. pim_ifp = ifp->info;
  36. zassert(pim_ifp);
  37. pim_ifp->pim_dr_addr = pim_ifp->primary_address;
  38. if (PIM_DEBUG_PIM_TRACE) {
  39. zlog_debug("%s: on interface %s",
  40. __PRETTY_FUNCTION__,
  41. ifp->name);
  42. }
  43. for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
  44. if (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) {
  45. pim_ifp->pim_dr_addr = neigh->source_addr;
  46. }
  47. }
  48. }
  49. static void dr_election_by_pri(struct interface *ifp)
  50. {
  51. struct pim_interface *pim_ifp;
  52. struct listnode *node;
  53. struct pim_neighbor *neigh;
  54. uint32_t dr_pri;
  55. pim_ifp = ifp->info;
  56. zassert(pim_ifp);
  57. pim_ifp->pim_dr_addr = pim_ifp->primary_address;
  58. dr_pri = pim_ifp->pim_dr_priority;
  59. if (PIM_DEBUG_PIM_TRACE) {
  60. zlog_debug("%s: dr pri %u on interface %s",
  61. __PRETTY_FUNCTION__,
  62. dr_pri, ifp->name);
  63. }
  64. for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
  65. if (PIM_DEBUG_PIM_TRACE) {
  66. zlog_info("%s: neigh pri %u addr %x if dr addr %x",
  67. __PRETTY_FUNCTION__,
  68. neigh->dr_priority,
  69. ntohl(neigh->source_addr.s_addr),
  70. ntohl(pim_ifp->pim_dr_addr.s_addr));
  71. }
  72. if (
  73. (neigh->dr_priority > dr_pri) ||
  74. (
  75. (neigh->dr_priority == dr_pri) &&
  76. (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr))
  77. )
  78. ) {
  79. pim_ifp->pim_dr_addr = neigh->source_addr;
  80. dr_pri = neigh->dr_priority;
  81. }
  82. }
  83. }
  84. /*
  85. RFC 4601: 4.3.2. DR Election
  86. A router's idea of the current DR on an interface can change when a
  87. PIM Hello message is received, when a neighbor times out, or when a
  88. router's own DR Priority changes.
  89. */
  90. int pim_if_dr_election(struct interface *ifp)
  91. {
  92. struct pim_interface *pim_ifp = ifp->info;
  93. struct in_addr old_dr_addr;
  94. ++pim_ifp->pim_dr_election_count;
  95. old_dr_addr = pim_ifp->pim_dr_addr;
  96. if (pim_ifp->pim_dr_num_nondrpri_neighbors) {
  97. dr_election_by_addr(ifp);
  98. }
  99. else {
  100. dr_election_by_pri(ifp);
  101. }
  102. /* DR changed ? */
  103. if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
  104. if (PIM_DEBUG_PIM_EVENTS) {
  105. char dr_old_str[100];
  106. char dr_new_str[100];
  107. pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str));
  108. pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str));
  109. zlog_debug("%s: DR was %s now is %s on interface %s",
  110. __PRETTY_FUNCTION__,
  111. dr_old_str, dr_new_str, ifp->name);
  112. }
  113. pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */
  114. ++pim_ifp->pim_dr_election_changes;
  115. pim_if_update_join_desired(pim_ifp);
  116. pim_if_update_could_assert(ifp);
  117. pim_if_update_assert_tracking_desired(ifp);
  118. return 1;
  119. }
  120. return 0;
  121. }
  122. static void update_dr_priority(struct pim_neighbor *neigh,
  123. pim_hello_options hello_options,
  124. uint32_t dr_priority)
  125. {
  126. pim_hello_options will_set_pri; /* boolean */
  127. pim_hello_options bit_flip; /* boolean */
  128. pim_hello_options pri_change; /* boolean */
  129. will_set_pri = PIM_OPTION_IS_SET(hello_options,
  130. PIM_OPTION_MASK_DR_PRIORITY);
  131. bit_flip =
  132. (
  133. will_set_pri !=
  134. PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)
  135. );
  136. if (bit_flip) {
  137. struct pim_interface *pim_ifp = neigh->interface->info;
  138. /* update num. of neighbors without dr_pri */
  139. if (will_set_pri) {
  140. --pim_ifp->pim_dr_num_nondrpri_neighbors;
  141. }
  142. else {
  143. ++pim_ifp->pim_dr_num_nondrpri_neighbors;
  144. }
  145. }
  146. pri_change =
  147. (
  148. bit_flip
  149. ||
  150. (neigh->dr_priority != dr_priority)
  151. );
  152. if (will_set_pri) {
  153. neigh->dr_priority = dr_priority;
  154. }
  155. else {
  156. neigh->dr_priority = 0; /* cosmetic unset */
  157. }
  158. if (pri_change) {
  159. /*
  160. RFC 4601: 4.3.2. DR Election
  161. A router's idea of the current DR on an interface can change when a
  162. PIM Hello message is received, when a neighbor times out, or when a
  163. router's own DR Priority changes.
  164. */
  165. pim_if_dr_election(neigh->interface); // router's own DR Priority changes
  166. }
  167. }
  168. static int on_neighbor_timer(struct thread *t)
  169. {
  170. struct pim_neighbor *neigh;
  171. struct interface *ifp;
  172. char msg[100];
  173. zassert(t);
  174. neigh = THREAD_ARG(t);
  175. zassert(neigh);
  176. ifp = neigh->interface;
  177. if (PIM_DEBUG_PIM_TRACE) {
  178. char src_str[100];
  179. pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
  180. zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s",
  181. neigh->holdtime, src_str, ifp->name);
  182. }
  183. neigh->t_expire_timer = 0;
  184. snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime);
  185. pim_neighbor_delete(ifp, neigh, msg);
  186. /*
  187. RFC 4601: 4.3.2. DR Election
  188. A router's idea of the current DR on an interface can change when a
  189. PIM Hello message is received, when a neighbor times out, or when a
  190. router's own DR Priority changes.
  191. */
  192. pim_if_dr_election(ifp); // neighbor times out
  193. return 0;
  194. }
  195. static void neighbor_timer_off(struct pim_neighbor *neigh)
  196. {
  197. if (PIM_DEBUG_PIM_TRACE) {
  198. if (neigh->t_expire_timer) {
  199. char src_str[100];
  200. pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
  201. zlog_debug("%s: cancelling timer for neighbor %s on %s",
  202. __PRETTY_FUNCTION__,
  203. src_str, neigh->interface->name);
  204. }
  205. }
  206. THREAD_OFF(neigh->t_expire_timer);
  207. zassert(!neigh->t_expire_timer);
  208. }
  209. void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
  210. {
  211. neigh->holdtime = holdtime;
  212. neighbor_timer_off(neigh);
  213. /*
  214. 0xFFFF is request for no holdtime
  215. */
  216. if (neigh->holdtime == 0xFFFF) {
  217. return;
  218. }
  219. if (PIM_DEBUG_PIM_TRACE) {
  220. char src_str[100];
  221. pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
  222. zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
  223. __PRETTY_FUNCTION__,
  224. neigh->holdtime, src_str, neigh->interface->name);
  225. }
  226. THREAD_TIMER_ON(master, neigh->t_expire_timer,
  227. on_neighbor_timer,
  228. neigh, neigh->holdtime);
  229. }
  230. static struct pim_neighbor *pim_neighbor_new(struct interface *ifp,
  231. struct in_addr source_addr,
  232. pim_hello_options hello_options,
  233. uint16_t holdtime,
  234. uint16_t propagation_delay,
  235. uint16_t override_interval,
  236. uint32_t dr_priority,
  237. uint32_t generation_id,
  238. struct list *addr_list)
  239. {
  240. struct pim_interface *pim_ifp;
  241. struct pim_neighbor *neigh;
  242. char src_str[100];
  243. zassert(ifp);
  244. pim_ifp = ifp->info;
  245. zassert(pim_ifp);
  246. neigh = XMALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
  247. if (!neigh) {
  248. zlog_err("%s: PIM XMALLOC(%zu) failure",
  249. __PRETTY_FUNCTION__, sizeof(*neigh));
  250. return 0;
  251. }
  252. neigh->creation = pim_time_monotonic_sec();
  253. neigh->source_addr = source_addr;
  254. neigh->hello_options = hello_options;
  255. neigh->propagation_delay_msec = propagation_delay;
  256. neigh->override_interval_msec = override_interval;
  257. neigh->dr_priority = dr_priority;
  258. neigh->generation_id = generation_id;
  259. neigh->prefix_list = addr_list;
  260. neigh->t_expire_timer = 0;
  261. neigh->interface = ifp;
  262. pim_neighbor_timer_reset(neigh, holdtime);
  263. pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str));
  264. if (PIM_DEBUG_PIM_EVENTS) {
  265. zlog_debug("%s: creating PIM neighbor %s on interface %s",
  266. __PRETTY_FUNCTION__,
  267. src_str, ifp->name);
  268. }
  269. zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s",
  270. src_str, ifp->name);
  271. if (neigh->propagation_delay_msec > pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
  272. pim_ifp->pim_neighbors_highest_propagation_delay_msec = neigh->propagation_delay_msec;
  273. }
  274. if (neigh->override_interval_msec > pim_ifp->pim_neighbors_highest_override_interval_msec) {
  275. pim_ifp->pim_neighbors_highest_override_interval_msec = neigh->override_interval_msec;
  276. }
  277. if (!PIM_OPTION_IS_SET(neigh->hello_options,
  278. PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
  279. /* update num. of neighbors without hello option lan_delay */
  280. ++pim_ifp->pim_number_of_nonlandelay_neighbors;
  281. }
  282. if (!PIM_OPTION_IS_SET(neigh->hello_options,
  283. PIM_OPTION_MASK_DR_PRIORITY)) {
  284. /* update num. of neighbors without hello option dr_pri */
  285. ++pim_ifp->pim_dr_num_nondrpri_neighbors;
  286. }
  287. return neigh;
  288. }
  289. static void delete_prefix_list(struct pim_neighbor *neigh)
  290. {
  291. if (neigh->prefix_list) {
  292. #ifdef DUMP_PREFIX_LIST
  293. struct listnode *p_node;
  294. struct prefix *p;
  295. char addr_str[10];
  296. int list_size = neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1;
  297. int i = 0;
  298. for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) {
  299. pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, sizeof(addr_str));
  300. zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
  301. __PRETTY_FUNCTION__,
  302. (unsigned) neigh, (unsigned) neigh->prefix_list, (unsigned) p,
  303. addr_str, i, list_size);
  304. ++i;
  305. }
  306. #endif
  307. list_delete(neigh->prefix_list);
  308. neigh->prefix_list = 0;
  309. }
  310. }
  311. void pim_neighbor_free(struct pim_neighbor *neigh)
  312. {
  313. zassert(!neigh->t_expire_timer);
  314. delete_prefix_list(neigh);
  315. XFREE(MTYPE_PIM_NEIGHBOR, neigh);
  316. }
  317. struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
  318. struct in_addr source_addr)
  319. {
  320. struct pim_interface *pim_ifp;
  321. struct listnode *node;
  322. struct pim_neighbor *neigh;
  323. pim_ifp = ifp->info;
  324. zassert(pim_ifp);
  325. for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
  326. if (source_addr.s_addr == neigh->source_addr.s_addr) {
  327. return neigh;
  328. }
  329. }
  330. return 0;
  331. }
  332. struct pim_neighbor *pim_neighbor_add(struct interface *ifp,
  333. struct in_addr source_addr,
  334. pim_hello_options hello_options,
  335. uint16_t holdtime,
  336. uint16_t propagation_delay,
  337. uint16_t override_interval,
  338. uint32_t dr_priority,
  339. uint32_t generation_id,
  340. struct list *addr_list)
  341. {
  342. struct pim_interface *pim_ifp;
  343. struct pim_neighbor *neigh;
  344. neigh = pim_neighbor_new(ifp, source_addr,
  345. hello_options,
  346. holdtime,
  347. propagation_delay,
  348. override_interval,
  349. dr_priority,
  350. generation_id,
  351. addr_list);
  352. if (!neigh) {
  353. return 0;
  354. }
  355. pim_ifp = ifp->info;
  356. zassert(pim_ifp);
  357. listnode_add(pim_ifp->pim_neighbor_list, neigh);
  358. /*
  359. RFC 4601: 4.3.2. DR Election
  360. A router's idea of the current DR on an interface can change when a
  361. PIM Hello message is received, when a neighbor times out, or when a
  362. router's own DR Priority changes.
  363. */
  364. pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election...
  365. /*
  366. RFC 4601: 4.3.1. Sending Hello Messages
  367. To allow new or rebooting routers to learn of PIM neighbors quickly,
  368. when a Hello message is received from a new neighbor, or a Hello
  369. message with a new GenID is received from an existing neighbor, a
  370. new Hello message should be sent on this interface after a
  371. randomized delay between 0 and Triggered_Hello_Delay.
  372. */
  373. pim_hello_restart_triggered(neigh->interface);
  374. return neigh;
  375. }
  376. static uint16_t
  377. find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp,
  378. struct pim_neighbor *highest_neigh)
  379. {
  380. struct pim_interface *pim_ifp;
  381. struct listnode *neigh_node;
  382. struct pim_neighbor *neigh;
  383. uint16_t next_highest_delay_msec;
  384. pim_ifp = ifp->info;
  385. zassert(pim_ifp);
  386. next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec;
  387. for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
  388. if (neigh == highest_neigh)
  389. continue;
  390. if (neigh->propagation_delay_msec > next_highest_delay_msec)
  391. next_highest_delay_msec = neigh->propagation_delay_msec;
  392. }
  393. return next_highest_delay_msec;
  394. }
  395. static uint16_t
  396. find_neighbors_next_highest_override_interval_msec(struct interface *ifp,
  397. struct pim_neighbor *highest_neigh)
  398. {
  399. struct pim_interface *pim_ifp;
  400. struct listnode *neigh_node;
  401. struct pim_neighbor *neigh;
  402. uint16_t next_highest_interval_msec;
  403. pim_ifp = ifp->info;
  404. zassert(pim_ifp);
  405. next_highest_interval_msec = pim_ifp->pim_override_interval_msec;
  406. for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
  407. if (neigh == highest_neigh)
  408. continue;
  409. if (neigh->override_interval_msec > next_highest_interval_msec)
  410. next_highest_interval_msec = neigh->override_interval_msec;
  411. }
  412. return next_highest_interval_msec;
  413. }
  414. void pim_neighbor_delete(struct interface *ifp,
  415. struct pim_neighbor *neigh,
  416. const char *delete_message)
  417. {
  418. struct pim_interface *pim_ifp;
  419. char src_str[100];
  420. pim_ifp = ifp->info;
  421. zassert(pim_ifp);
  422. pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
  423. zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
  424. src_str, ifp->name, delete_message);
  425. neighbor_timer_off(neigh);
  426. pim_if_assert_on_neighbor_down(ifp, neigh->source_addr);
  427. if (!PIM_OPTION_IS_SET(neigh->hello_options,
  428. PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
  429. /* update num. of neighbors without hello option lan_delay */
  430. --pim_ifp->pim_number_of_nonlandelay_neighbors;
  431. }
  432. if (!PIM_OPTION_IS_SET(neigh->hello_options,
  433. PIM_OPTION_MASK_DR_PRIORITY)) {
  434. /* update num. of neighbors without dr_pri */
  435. --pim_ifp->pim_dr_num_nondrpri_neighbors;
  436. }
  437. zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
  438. zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec);
  439. if (pim_if_lan_delay_enabled(ifp)) {
  440. /* will delete a neighbor with highest propagation delay? */
  441. if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
  442. /* then find the next highest propagation delay */
  443. pim_ifp->pim_neighbors_highest_propagation_delay_msec =
  444. find_neighbors_next_highest_propagation_delay_msec(ifp, neigh);
  445. }
  446. /* will delete a neighbor with highest override interval? */
  447. if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) {
  448. /* then find the next highest propagation delay */
  449. pim_ifp->pim_neighbors_highest_override_interval_msec =
  450. find_neighbors_next_highest_override_interval_msec(ifp, neigh);
  451. }
  452. }
  453. if (PIM_DEBUG_PIM_TRACE) {
  454. zlog_debug("%s: deleting PIM neighbor %s on interface %s",
  455. __PRETTY_FUNCTION__,
  456. src_str, ifp->name);
  457. }
  458. listnode_delete(pim_ifp->pim_neighbor_list, neigh);
  459. pim_neighbor_free(neigh);
  460. }
  461. void pim_neighbor_delete_all(struct interface *ifp,
  462. const char *delete_message)
  463. {
  464. struct pim_interface *pim_ifp;
  465. struct listnode *neigh_node;
  466. struct listnode *neigh_nextnode;
  467. struct pim_neighbor *neigh;
  468. pim_ifp = ifp->info;
  469. zassert(pim_ifp);
  470. for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
  471. neigh_nextnode, neigh)) {
  472. pim_neighbor_delete(ifp, neigh, delete_message);
  473. }
  474. }
  475. struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
  476. struct in_addr addr)
  477. {
  478. struct listnode *node;
  479. struct prefix *p;
  480. if (!neigh->prefix_list)
  481. return 0;
  482. for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) {
  483. if (p->family == AF_INET) {
  484. if (addr.s_addr == p->u.prefix4.s_addr) {
  485. return p;
  486. }
  487. }
  488. }
  489. return 0;
  490. }
  491. /*
  492. RFC 4601: 4.3.4. Maintaining Secondary Address Lists
  493. All the advertised secondary addresses in received Hello messages
  494. must be checked against those previously advertised by all other
  495. PIM neighbors on that interface. If there is a conflict and the
  496. same secondary address was previously advertised by another
  497. neighbor, then only the most recently received mapping MUST be
  498. maintained, and an error message SHOULD be logged to the
  499. administrator in a rate-limited manner.
  500. */
  501. static void delete_from_neigh_addr(struct interface *ifp,
  502. struct list *addr_list,
  503. struct in_addr neigh_addr)
  504. {
  505. struct listnode *addr_node;
  506. struct prefix *addr;
  507. struct pim_interface *pim_ifp;
  508. pim_ifp = ifp->info;
  509. zassert(pim_ifp);
  510. zassert(addr_list);
  511. /*
  512. Scan secondary address list
  513. */
  514. for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node,
  515. addr)) {
  516. struct listnode *neigh_node;
  517. struct pim_neighbor *neigh;
  518. if (addr->family != AF_INET)
  519. continue;
  520. /*
  521. Scan neighbors
  522. */
  523. for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
  524. neigh)) {
  525. {
  526. struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4);
  527. if (p) {
  528. char addr_str[100];
  529. char this_neigh_str[100];
  530. char other_neigh_str[100];
  531. pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str));
  532. pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str));
  533. pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str));
  534. zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
  535. addr_str, this_neigh_str, other_neigh_str, ifp->name);
  536. listnode_delete(neigh->prefix_list, p);
  537. prefix_free(p);
  538. }
  539. }
  540. } /* scan neighbors */
  541. } /* scan addr list */
  542. }
  543. void pim_neighbor_update(struct pim_neighbor *neigh,
  544. pim_hello_options hello_options,
  545. uint16_t holdtime,
  546. uint32_t dr_priority,
  547. struct list *addr_list)
  548. {
  549. struct pim_interface *pim_ifp = neigh->interface->info;
  550. /* Received holdtime ? */
  551. if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
  552. pim_neighbor_timer_reset(neigh, holdtime);
  553. }
  554. else {
  555. pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
  556. }
  557. #ifdef DUMP_PREFIX_LIST
  558. zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
  559. __PRETTY_FUNCTION__,
  560. (unsigned) neigh->prefix_list,
  561. neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1,
  562. (unsigned) addr_list,
  563. addr_list ? (int) listcount(addr_list) : -1);
  564. #endif
  565. if (neigh->prefix_list == addr_list) {
  566. if (addr_list) {
  567. zlog_err("%s: internal error: trying to replace same prefix list=%p",
  568. __PRETTY_FUNCTION__, (void *) addr_list);
  569. }
  570. }
  571. else {
  572. /* Delete existing secondary address list */
  573. delete_prefix_list(neigh);
  574. }
  575. if (addr_list) {
  576. delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr);
  577. }
  578. /* Replace secondary address list */
  579. neigh->prefix_list = addr_list;
  580. update_dr_priority(neigh,
  581. hello_options,
  582. dr_priority);
  583. /*
  584. Copy flags
  585. */
  586. neigh->hello_options = hello_options;
  587. }