pim_pim.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  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 "thread.h"
  21. #include "memory.h"
  22. #include "pimd.h"
  23. #include "pim_pim.h"
  24. #include "pim_time.h"
  25. #include "pim_iface.h"
  26. #include "pim_sock.h"
  27. #include "pim_str.h"
  28. #include "pim_util.h"
  29. #include "pim_tlv.h"
  30. #include "pim_neighbor.h"
  31. #include "pim_hello.h"
  32. #include "pim_join.h"
  33. #include "pim_assert.h"
  34. #include "pim_msg.h"
  35. static int on_pim_hello_send(struct thread *t);
  36. static int pim_hello_send(struct interface *ifp,
  37. uint16_t holdtime);
  38. static void sock_close(struct interface *ifp)
  39. {
  40. struct pim_interface *pim_ifp = ifp->info;
  41. if (PIM_DEBUG_PIM_TRACE) {
  42. if (pim_ifp->t_pim_sock_read) {
  43. zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
  44. pim_ifp->pim_sock_fd,
  45. ifp->name);
  46. }
  47. }
  48. THREAD_OFF(pim_ifp->t_pim_sock_read);
  49. if (PIM_DEBUG_PIM_TRACE) {
  50. if (pim_ifp->t_pim_hello_timer) {
  51. zlog_debug("Cancelling PIM hello timer for interface %s",
  52. ifp->name);
  53. }
  54. }
  55. THREAD_OFF(pim_ifp->t_pim_hello_timer);
  56. if (PIM_DEBUG_PIM_TRACE) {
  57. zlog_debug("Deleting PIM socket fd=%d on interface %s",
  58. pim_ifp->pim_sock_fd, ifp->name);
  59. }
  60. if (close(pim_ifp->pim_sock_fd)) {
  61. zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
  62. pim_ifp->pim_sock_fd, ifp->name,
  63. errno, safe_strerror(errno));
  64. }
  65. pim_ifp->pim_sock_fd = -1;
  66. pim_ifp->pim_sock_creation = 0;
  67. zassert(pim_ifp->pim_sock_fd < 0);
  68. zassert(!pim_ifp->t_pim_sock_read);
  69. zassert(!pim_ifp->t_pim_hello_timer);
  70. zassert(!pim_ifp->pim_sock_creation);
  71. }
  72. void pim_sock_delete(struct interface *ifp, const char *delete_message)
  73. {
  74. zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
  75. ifp->name, delete_message);
  76. if (!ifp->info) {
  77. zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
  78. __PRETTY_FUNCTION__, delete_message, ifp->name);
  79. return;
  80. }
  81. /*
  82. RFC 4601: 4.3.1. Sending Hello Messages
  83. Before an interface goes down or changes primary IP address, a Hello
  84. message with a zero HoldTime should be sent immediately (with the
  85. old IP address if the IP address changed).
  86. */
  87. pim_hello_send(ifp, 0 /* zero-sec holdtime */);
  88. pim_neighbor_delete_all(ifp, delete_message);
  89. sock_close(ifp);
  90. }
  91. int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
  92. {
  93. struct ip *ip_hdr;
  94. size_t ip_hlen; /* ip header length in bytes */
  95. char src_str[100];
  96. char dst_str[100];
  97. uint8_t *pim_msg;
  98. int pim_msg_len;
  99. uint8_t pim_version;
  100. uint8_t pim_type;
  101. uint16_t pim_checksum; /* received checksum */
  102. uint16_t checksum; /* computed checksum */
  103. struct pim_neighbor *neigh;
  104. if (!ifp->info) {
  105. zlog_warn("%s: PIM not enabled on interface %s",
  106. __PRETTY_FUNCTION__, ifp->name);
  107. return -1;
  108. }
  109. if (len < sizeof(*ip_hdr)) {
  110. zlog_warn("PIM packet size=%zu shorter than minimum=%zu",
  111. len, sizeof(*ip_hdr));
  112. return -1;
  113. }
  114. ip_hdr = (struct ip *) buf;
  115. pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));
  116. pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str));
  117. ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
  118. if (PIM_DEBUG_PIM_PACKETS) {
  119. zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d",
  120. src_str, dst_str, ifp->name, len, ip_hlen, ip_hdr->ip_p);
  121. }
  122. if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) {
  123. zlog_warn("IP packet protocol=%d is not PIM=%d",
  124. ip_hdr->ip_p, PIM_IP_PROTO_PIM);
  125. return -1;
  126. }
  127. if (ip_hlen < PIM_IP_HEADER_MIN_LEN) {
  128. zlog_warn("IP packet header size=%zu shorter than minimum=%d",
  129. ip_hlen, PIM_IP_HEADER_MIN_LEN);
  130. return -1;
  131. }
  132. if (ip_hlen > PIM_IP_HEADER_MAX_LEN) {
  133. zlog_warn("IP packet header size=%zu greater than maximum=%d",
  134. ip_hlen, PIM_IP_HEADER_MAX_LEN);
  135. return -1;
  136. }
  137. pim_msg = buf + ip_hlen;
  138. pim_msg_len = len - ip_hlen;
  139. if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
  140. pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len);
  141. }
  142. if (pim_msg_len < PIM_PIM_MIN_LEN) {
  143. zlog_warn("PIM message size=%d shorter than minimum=%d",
  144. pim_msg_len, PIM_PIM_MIN_LEN);
  145. return -1;
  146. }
  147. pim_version = PIM_MSG_HDR_GET_VERSION(pim_msg);
  148. pim_type = PIM_MSG_HDR_GET_TYPE(pim_msg);
  149. if (pim_version != PIM_PROTO_VERSION) {
  150. zlog_warn("Ignoring PIM pkt from %s with unsupported version: %d",
  151. ifp->name, pim_version);
  152. return -1;
  153. }
  154. /* save received checksum */
  155. pim_checksum = PIM_MSG_HDR_GET_CHECKSUM(pim_msg);
  156. /* for computing checksum */
  157. *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
  158. checksum = in_cksum(pim_msg, pim_msg_len);
  159. if (checksum != pim_checksum) {
  160. zlog_warn("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
  161. ifp->name, pim_checksum, checksum);
  162. return -1;
  163. }
  164. if (PIM_DEBUG_PIM_PACKETS) {
  165. zlog_debug("Recv PIM packet from %s to %s on %s: ttl=%d pim_version=%d pim_type=%d pim_msg_size=%d checksum=%x",
  166. src_str, dst_str, ifp->name, ip_hdr->ip_ttl,
  167. pim_version, pim_type, pim_msg_len, checksum);
  168. }
  169. if (pim_type == PIM_MSG_TYPE_REGISTER ||
  170. pim_type == PIM_MSG_TYPE_REG_STOP ||
  171. pim_type == PIM_MSG_TYPE_BOOTSTRAP ||
  172. pim_type == PIM_MSG_TYPE_GRAFT ||
  173. pim_type == PIM_MSG_TYPE_GRAFT_ACK ||
  174. pim_type == PIM_MSG_TYPE_CANDIDATE)
  175. {
  176. if (PIM_DEBUG_PIM_PACKETS) {
  177. zlog_debug("Recv PIM packet type %d which is not currently understood",
  178. pim_type);
  179. }
  180. return -1;
  181. }
  182. if (pim_type == PIM_MSG_TYPE_HELLO) {
  183. int result = pim_hello_recv(ifp,
  184. ip_hdr->ip_src,
  185. pim_msg + PIM_MSG_HEADER_LEN,
  186. pim_msg_len - PIM_MSG_HEADER_LEN);
  187. return result;
  188. }
  189. neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
  190. if (!neigh) {
  191. zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
  192. __FILE__, __PRETTY_FUNCTION__,
  193. pim_type, src_str, ifp->name);
  194. return -1;
  195. }
  196. switch (pim_type) {
  197. case PIM_MSG_TYPE_JOIN_PRUNE:
  198. return pim_joinprune_recv(ifp, neigh,
  199. ip_hdr->ip_src,
  200. pim_msg + PIM_MSG_HEADER_LEN,
  201. pim_msg_len - PIM_MSG_HEADER_LEN);
  202. case PIM_MSG_TYPE_ASSERT:
  203. return pim_assert_recv(ifp, neigh,
  204. ip_hdr->ip_src,
  205. pim_msg + PIM_MSG_HEADER_LEN,
  206. pim_msg_len - PIM_MSG_HEADER_LEN);
  207. default:
  208. zlog_warn("%s %s: unsupported PIM message type=%d from %s on %s",
  209. __FILE__, __PRETTY_FUNCTION__,
  210. pim_type, src_str, ifp->name);
  211. }
  212. return -1;
  213. }
  214. static void pim_sock_read_on(struct interface *ifp);
  215. static int pim_sock_read(struct thread *t)
  216. {
  217. struct interface *ifp;
  218. struct pim_interface *pim_ifp;
  219. int fd;
  220. struct sockaddr_in from;
  221. struct sockaddr_in to;
  222. socklen_t fromlen = sizeof(from);
  223. socklen_t tolen = sizeof(to);
  224. uint8_t buf[PIM_PIM_BUFSIZE_READ];
  225. int len;
  226. ifindex_t ifindex = -1;
  227. int result = -1; /* defaults to bad */
  228. zassert(t);
  229. ifp = THREAD_ARG(t);
  230. zassert(ifp);
  231. fd = THREAD_FD(t);
  232. pim_ifp = ifp->info;
  233. zassert(pim_ifp);
  234. zassert(fd == pim_ifp->pim_sock_fd);
  235. len = pim_socket_recvfromto(fd, buf, sizeof(buf),
  236. &from, &fromlen,
  237. &to, &tolen,
  238. &ifindex);
  239. if (len < 0) {
  240. zlog_warn("Failure receiving IP PIM packet on fd=%d: errno=%d: %s",
  241. fd, errno, safe_strerror(errno));
  242. goto done;
  243. }
  244. if (PIM_DEBUG_PIM_PACKETS) {
  245. char from_str[100];
  246. char to_str[100];
  247. if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str)))
  248. sprintf(from_str, "<from?>");
  249. if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str)))
  250. sprintf(to_str, "<to?>");
  251. zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)",
  252. len, from_str, to_str, fd, ifindex, ifp->ifindex);
  253. }
  254. if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
  255. pim_pkt_dump(__PRETTY_FUNCTION__, buf, len);
  256. }
  257. #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
  258. /* ifindex sanity check */
  259. if (ifindex != (int) ifp->ifindex) {
  260. char from_str[100];
  261. char to_str[100];
  262. struct interface *recv_ifp;
  263. if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str)))
  264. sprintf(from_str, "<from?>");
  265. if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str)))
  266. sprintf(to_str, "<to?>");
  267. recv_ifp = if_lookup_by_index(ifindex);
  268. if (recv_ifp) {
  269. zassert(ifindex == (int) recv_ifp->ifindex);
  270. }
  271. #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
  272. zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
  273. from_str, to_str, fd,
  274. ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>",
  275. ifp->ifindex, ifp->name);
  276. #endif
  277. goto done;
  278. }
  279. #endif
  280. int fail = pim_pim_packet(ifp, buf, len);
  281. if (fail) {
  282. zlog_warn("%s: pim_pim_packet() return=%d",
  283. __PRETTY_FUNCTION__, fail);
  284. goto done;
  285. }
  286. result = 0; /* good */
  287. done:
  288. pim_sock_read_on(ifp);
  289. if (result) {
  290. ++pim_ifp->pim_ifstat_hello_recvfail;
  291. }
  292. return result;
  293. }
  294. static void pim_sock_read_on(struct interface *ifp)
  295. {
  296. struct pim_interface *pim_ifp;
  297. zassert(ifp);
  298. zassert(ifp->info);
  299. pim_ifp = ifp->info;
  300. if (PIM_DEBUG_PIM_TRACE) {
  301. zlog_debug("Scheduling READ event on PIM socket fd=%d",
  302. pim_ifp->pim_sock_fd);
  303. }
  304. pim_ifp->t_pim_sock_read = 0;
  305. zassert(!pim_ifp->t_pim_sock_read);
  306. THREAD_READ_ON(master, pim_ifp->t_pim_sock_read, pim_sock_read, ifp,
  307. pim_ifp->pim_sock_fd);
  308. }
  309. static int pim_sock_open(struct in_addr ifaddr, ifindex_t ifindex)
  310. {
  311. int fd;
  312. fd = pim_socket_mcast(IPPROTO_PIM, ifaddr, 0 /* loop=false */);
  313. if (fd < 0)
  314. return -1;
  315. if (pim_socket_join(fd, qpim_all_pim_routers_addr, ifaddr, ifindex)) {
  316. close(fd);
  317. return -2;
  318. }
  319. return fd;
  320. }
  321. void pim_ifstat_reset(struct interface *ifp)
  322. {
  323. struct pim_interface *pim_ifp;
  324. zassert(ifp);
  325. pim_ifp = ifp->info;
  326. if (!pim_ifp) {
  327. return;
  328. }
  329. pim_ifp->pim_ifstat_start = pim_time_monotonic_sec();
  330. pim_ifp->pim_ifstat_hello_sent = 0;
  331. pim_ifp->pim_ifstat_hello_sendfail = 0;
  332. pim_ifp->pim_ifstat_hello_recv = 0;
  333. pim_ifp->pim_ifstat_hello_recvfail = 0;
  334. }
  335. void pim_sock_reset(struct interface *ifp)
  336. {
  337. struct pim_interface *pim_ifp;
  338. zassert(ifp);
  339. zassert(ifp->info);
  340. pim_ifp = ifp->info;
  341. pim_ifp->primary_address = pim_find_primary_addr(ifp);
  342. pim_ifp->pim_sock_fd = -1;
  343. pim_ifp->pim_sock_creation = 0;
  344. pim_ifp->t_pim_sock_read = 0;
  345. pim_ifp->t_pim_hello_timer = 0;
  346. pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
  347. pim_ifp->pim_default_holdtime = -1; /* unset: means 3.5 * pim_hello_period */
  348. pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY;
  349. pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
  350. pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
  351. pim_ifp->pim_override_interval_msec = PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
  352. if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) {
  353. PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
  354. }
  355. else {
  356. PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
  357. }
  358. /* neighbors without lan_delay */
  359. pim_ifp->pim_number_of_nonlandelay_neighbors = 0;
  360. pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0;
  361. pim_ifp->pim_neighbors_highest_override_interval_msec = 0;
  362. /* DR Election */
  363. pim_ifp->pim_dr_election_last = 0; /* timestamp */
  364. pim_ifp->pim_dr_election_count = 0;
  365. pim_ifp->pim_dr_election_changes = 0;
  366. pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */
  367. pim_ifp->pim_dr_addr = pim_ifp->primary_address;
  368. pim_ifstat_reset(ifp);
  369. }
  370. int pim_msg_send(int fd,
  371. struct in_addr dst,
  372. uint8_t *pim_msg,
  373. int pim_msg_size,
  374. const char *ifname)
  375. {
  376. ssize_t sent;
  377. struct sockaddr_in to;
  378. socklen_t tolen;
  379. if (PIM_DEBUG_PIM_PACKETS) {
  380. char dst_str[100];
  381. pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
  382. zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
  383. __PRETTY_FUNCTION__,
  384. dst_str, ifname, pim_msg_size,
  385. *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg));
  386. }
  387. #if 0
  388. memset(&to, 0, sizeof(to));
  389. #endif
  390. to.sin_family = AF_INET;
  391. to.sin_addr = dst;
  392. #if 0
  393. to.sin_port = htons(0);
  394. #endif
  395. tolen = sizeof(to);
  396. if (PIM_DEBUG_PIM_PACKETDUMP_SEND) {
  397. pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size);
  398. }
  399. sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT,
  400. (struct sockaddr *)&to, tolen);
  401. if (sent != (ssize_t) pim_msg_size) {
  402. int e = errno;
  403. char dst_str[100];
  404. pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
  405. if (sent < 0) {
  406. zlog_warn("%s: sendto() failure to %s on %s: fd=%d msg_size=%d: errno=%d: %s",
  407. __PRETTY_FUNCTION__,
  408. dst_str, ifname, fd, pim_msg_size,
  409. e, safe_strerror(e));
  410. }
  411. else {
  412. zlog_warn("%s: sendto() partial to %s on %s: fd=%d msg_size=%d: sent=%zd",
  413. __PRETTY_FUNCTION__,
  414. dst_str, ifname, fd,
  415. pim_msg_size, sent);
  416. }
  417. return -1;
  418. }
  419. return 0;
  420. }
  421. static int hello_send(struct interface *ifp,
  422. uint16_t holdtime)
  423. {
  424. uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE];
  425. struct pim_interface *pim_ifp;
  426. int pim_tlv_size;
  427. int pim_msg_size;
  428. pim_ifp = ifp->info;
  429. if (PIM_DEBUG_PIM_HELLO) {
  430. char dst_str[100];
  431. pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str));
  432. zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d",
  433. __PRETTY_FUNCTION__,
  434. dst_str, ifp->name,
  435. holdtime,
  436. pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec,
  437. PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
  438. pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
  439. listcount(ifp->connected));
  440. }
  441. pim_tlv_size = pim_hello_build_tlv(ifp->name,
  442. pim_msg + PIM_PIM_MIN_LEN,
  443. sizeof(pim_msg) - PIM_PIM_MIN_LEN,
  444. holdtime,
  445. pim_ifp->pim_dr_priority,
  446. pim_ifp->pim_generation_id,
  447. pim_ifp->pim_propagation_delay_msec,
  448. pim_ifp->pim_override_interval_msec,
  449. PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
  450. ifp->connected);
  451. if (pim_tlv_size < 0) {
  452. return -1;
  453. }
  454. pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
  455. zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
  456. zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
  457. pim_msg_build_header(pim_msg, pim_msg_size,
  458. PIM_MSG_TYPE_HELLO);
  459. if (pim_msg_send(pim_ifp->pim_sock_fd,
  460. qpim_all_pim_routers_addr,
  461. pim_msg,
  462. pim_msg_size,
  463. ifp->name)) {
  464. if (PIM_DEBUG_PIM_HELLO) {
  465. zlog_debug("%s: could not send PIM message on interface %s",
  466. __PRETTY_FUNCTION__, ifp->name);
  467. }
  468. return -2;
  469. }
  470. return 0;
  471. }
  472. static int pim_hello_send(struct interface *ifp,
  473. uint16_t holdtime)
  474. {
  475. struct pim_interface *pim_ifp;
  476. zassert(ifp);
  477. pim_ifp = ifp->info;
  478. zassert(pim_ifp);
  479. if (hello_send(ifp, holdtime)) {
  480. ++pim_ifp->pim_ifstat_hello_sendfail;
  481. if (PIM_DEBUG_PIM_HELLO) {
  482. zlog_warn("Could not send PIM hello on interface %s",
  483. ifp->name);
  484. }
  485. return -1;
  486. }
  487. ++pim_ifp->pim_ifstat_hello_sent;
  488. return 0;
  489. }
  490. static void hello_resched(struct interface *ifp)
  491. {
  492. struct pim_interface *pim_ifp;
  493. zassert(ifp);
  494. pim_ifp = ifp->info;
  495. zassert(pim_ifp);
  496. if (PIM_DEBUG_PIM_HELLO) {
  497. zlog_debug("Rescheduling %d sec hello on interface %s",
  498. pim_ifp->pim_hello_period, ifp->name);
  499. }
  500. THREAD_OFF(pim_ifp->t_pim_hello_timer);
  501. THREAD_TIMER_ON(master, pim_ifp->t_pim_hello_timer,
  502. on_pim_hello_send,
  503. ifp, pim_ifp->pim_hello_period);
  504. }
  505. /*
  506. Periodic hello timer
  507. */
  508. static int on_pim_hello_send(struct thread *t)
  509. {
  510. struct pim_interface *pim_ifp;
  511. struct interface *ifp;
  512. zassert(t);
  513. ifp = THREAD_ARG(t);
  514. zassert(ifp);
  515. pim_ifp = ifp->info;
  516. /*
  517. * Schedule next hello
  518. */
  519. pim_ifp->t_pim_hello_timer = 0;
  520. hello_resched(ifp);
  521. /*
  522. * Send hello
  523. */
  524. return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
  525. }
  526. /*
  527. RFC 4601: 4.3.1. Sending Hello Messages
  528. Thus, if a router needs to send a Join/Prune or Assert message on an
  529. interface on which it has not yet sent a Hello message with the
  530. currently configured IP address, then it MUST immediately send the
  531. relevant Hello message without waiting for the Hello Timer to
  532. expire, followed by the Join/Prune or Assert message.
  533. */
  534. void pim_hello_restart_now(struct interface *ifp)
  535. {
  536. struct pim_interface *pim_ifp;
  537. zassert(ifp);
  538. pim_ifp = ifp->info;
  539. zassert(pim_ifp);
  540. /*
  541. * Reset next hello timer
  542. */
  543. hello_resched(ifp);
  544. /*
  545. * Immediately send hello
  546. */
  547. pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
  548. }
  549. /*
  550. RFC 4601: 4.3.1. Sending Hello Messages
  551. To allow new or rebooting routers to learn of PIM neighbors quickly,
  552. when a Hello message is received from a new neighbor, or a Hello
  553. message with a new GenID is received from an existing neighbor, a
  554. new Hello message should be sent on this interface after a
  555. randomized delay between 0 and Triggered_Hello_Delay.
  556. */
  557. void pim_hello_restart_triggered(struct interface *ifp)
  558. {
  559. struct pim_interface *pim_ifp;
  560. int triggered_hello_delay_msec;
  561. int random_msec;
  562. zassert(ifp);
  563. pim_ifp = ifp->info;
  564. zassert(pim_ifp);
  565. triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
  566. if (pim_ifp->t_pim_hello_timer) {
  567. long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer);
  568. if (remain_msec <= triggered_hello_delay_msec) {
  569. /* Rescheduling hello would increase the delay, then it's faster
  570. to just wait for the scheduled periodic hello. */
  571. return;
  572. }
  573. THREAD_OFF(pim_ifp->t_pim_hello_timer);
  574. pim_ifp->t_pim_hello_timer = 0;
  575. }
  576. zassert(!pim_ifp->t_pim_hello_timer);
  577. random_msec = random() % (triggered_hello_delay_msec + 1);
  578. if (PIM_DEBUG_PIM_HELLO) {
  579. zlog_debug("Scheduling %d msec triggered hello on interface %s",
  580. random_msec, ifp->name);
  581. }
  582. THREAD_TIMER_MSEC_ON(master, pim_ifp->t_pim_hello_timer,
  583. on_pim_hello_send,
  584. ifp, random_msec);
  585. }
  586. int pim_sock_add(struct interface *ifp)
  587. {
  588. struct pim_interface *pim_ifp;
  589. struct in_addr ifaddr;
  590. uint32_t old_genid;
  591. pim_ifp = ifp->info;
  592. zassert(pim_ifp);
  593. if (pim_ifp->pim_sock_fd >= 0) {
  594. zlog_warn("Can't recreate existing PIM socket fd=%d for interface %s",
  595. pim_ifp->pim_sock_fd, ifp->name);
  596. return -1;
  597. }
  598. ifaddr = pim_ifp->primary_address;
  599. pim_ifp->pim_sock_fd = pim_sock_open(ifaddr, ifp->ifindex);
  600. if (pim_ifp->pim_sock_fd < 0) {
  601. zlog_warn("Could not open PIM socket on interface %s",
  602. ifp->name);
  603. return -2;
  604. }
  605. pim_ifp->t_pim_sock_read = 0;
  606. pim_ifp->pim_sock_creation = pim_time_monotonic_sec();
  607. /*
  608. * Just ensure that the new generation id
  609. * actually chooses something different.
  610. * Actually ran across a case where this
  611. * happened, pre-switch to random().
  612. * While this is unlikely to happen now
  613. * let's make sure it doesn't.
  614. */
  615. old_genid = pim_ifp->pim_generation_id;
  616. while (old_genid == pim_ifp->pim_generation_id)
  617. pim_ifp->pim_generation_id = random();
  618. zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
  619. ifp->name, ifp->ifindex);
  620. /*
  621. * Start receiving PIM messages
  622. */
  623. pim_sock_read_on(ifp);
  624. /*
  625. * Start sending PIM hello's
  626. */
  627. pim_hello_restart_triggered(ifp);
  628. return 0;
  629. }