pim_zebra.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  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 "zebra/rib.h"
  20. #include "if.h"
  21. #include "log.h"
  22. #include "prefix.h"
  23. #include "zclient.h"
  24. #include "stream.h"
  25. #include "network.h"
  26. #include "pimd.h"
  27. #include "pim_pim.h"
  28. #include "pim_zebra.h"
  29. #include "pim_iface.h"
  30. #include "pim_str.h"
  31. #include "pim_oil.h"
  32. #include "pim_rpf.h"
  33. #include "pim_time.h"
  34. #include "pim_join.h"
  35. #include "pim_zlookup.h"
  36. #include "pim_ifchannel.h"
  37. #undef PIM_DEBUG_IFADDR_DUMP
  38. #define PIM_DEBUG_IFADDR_DUMP
  39. static int fib_lookup_if_vif_index(struct in_addr addr);
  40. static int del_oif(struct channel_oil *channel_oil,
  41. struct interface *oif,
  42. uint32_t proto_mask);
  43. #if 0
  44. static void zclient_broken(struct zclient *zclient)
  45. {
  46. struct listnode *ifnode;
  47. struct interface *ifp;
  48. zlog_warn("%s %s: broken zclient connection",
  49. __FILE__, __PRETTY_FUNCTION__);
  50. for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
  51. pim_if_addr_del_all(ifp);
  52. }
  53. /* upon return, zclient will discard connected addresses */
  54. }
  55. #endif
  56. /* Router-id update message from zebra. */
  57. static int pim_router_id_update_zebra(int command, struct zclient *zclient,
  58. zebra_size_t length, vrf_id_t vrf_id)
  59. {
  60. struct prefix router_id;
  61. zebra_router_id_update_read(zclient->ibuf, &router_id);
  62. return 0;
  63. }
  64. static int pim_zebra_if_add(int command, struct zclient *zclient,
  65. zebra_size_t length, vrf_id_t vrf_id)
  66. {
  67. struct interface *ifp;
  68. /*
  69. zebra api adds/dels interfaces using the same call
  70. interface_add_read below, see comments in lib/zclient.c
  71. */
  72. ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
  73. if (!ifp)
  74. return 0;
  75. if (PIM_DEBUG_ZEBRA) {
  76. zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
  77. __PRETTY_FUNCTION__,
  78. ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
  79. ifp->mtu, if_is_operative(ifp));
  80. }
  81. if (if_is_operative(ifp))
  82. pim_if_addr_add_all(ifp);
  83. return 0;
  84. }
  85. static int pim_zebra_if_del(int command, struct zclient *zclient,
  86. zebra_size_t length, vrf_id_t vrf_id)
  87. {
  88. struct interface *ifp;
  89. /*
  90. zebra api adds/dels interfaces using the same call
  91. interface_add_read below, see comments in lib/zclient.c
  92. comments in lib/zclient.c seem to indicate that calling
  93. zebra_interface_add_read is the correct call, but that
  94. results in an attemted out of bounds read which causes
  95. pimd to assert. Other clients use zebra_interface_state_read
  96. and it appears to work just fine.
  97. */
  98. ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
  99. if (!ifp)
  100. return 0;
  101. if (PIM_DEBUG_ZEBRA) {
  102. zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
  103. __PRETTY_FUNCTION__,
  104. ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
  105. ifp->mtu, if_is_operative(ifp));
  106. }
  107. if (!if_is_operative(ifp))
  108. pim_if_addr_del_all(ifp);
  109. return 0;
  110. }
  111. static int pim_zebra_if_state_up(int command, struct zclient *zclient,
  112. zebra_size_t length, vrf_id_t vrf_id)
  113. {
  114. struct interface *ifp;
  115. /*
  116. zebra api notifies interface up/down events by using the same call
  117. zebra_interface_state_read below, see comments in lib/zclient.c
  118. */
  119. ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
  120. if (!ifp)
  121. return 0;
  122. zlog_info("INTERFACE UP: %s ifindex=%d", ifp->name, ifp->ifindex);
  123. if (PIM_DEBUG_ZEBRA) {
  124. zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
  125. __PRETTY_FUNCTION__,
  126. ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
  127. ifp->mtu, if_is_operative(ifp));
  128. }
  129. if (if_is_operative(ifp)) {
  130. /*
  131. pim_if_addr_add_all() suffices for bringing up both IGMP and PIM
  132. */
  133. pim_if_addr_add_all(ifp);
  134. }
  135. return 0;
  136. }
  137. static int pim_zebra_if_state_down(int command, struct zclient *zclient,
  138. zebra_size_t length, vrf_id_t vrf_id)
  139. {
  140. struct interface *ifp;
  141. /*
  142. zebra api notifies interface up/down events by using the same call
  143. zebra_interface_state_read below, see comments in lib/zclient.c
  144. */
  145. ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
  146. if (!ifp)
  147. return 0;
  148. zlog_info("INTERFACE DOWN: %s ifindex=%d", ifp->name, ifp->ifindex);
  149. if (PIM_DEBUG_ZEBRA) {
  150. zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
  151. __PRETTY_FUNCTION__,
  152. ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric,
  153. ifp->mtu, if_is_operative(ifp));
  154. }
  155. if (!if_is_operative(ifp)) {
  156. /*
  157. pim_if_addr_del_all() suffices for shutting down IGMP,
  158. but not for shutting down PIM
  159. */
  160. pim_if_addr_del_all(ifp);
  161. /*
  162. pim_sock_delete() closes the socket, stops read and timer threads,
  163. and kills all neighbors.
  164. */
  165. if (ifp->info) {
  166. pim_sock_delete(ifp, "link down");
  167. }
  168. }
  169. return 0;
  170. }
  171. #ifdef PIM_DEBUG_IFADDR_DUMP
  172. static void dump_if_address(struct interface *ifp)
  173. {
  174. struct connected *ifc;
  175. struct listnode *node;
  176. zlog_debug("%s %s: interface %s addresses:",
  177. __FILE__, __PRETTY_FUNCTION__,
  178. ifp->name);
  179. for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
  180. struct prefix *p = ifc->address;
  181. if (p->family != AF_INET)
  182. continue;
  183. zlog_debug("%s %s: interface %s address %s %s",
  184. __FILE__, __PRETTY_FUNCTION__,
  185. ifp->name,
  186. inet_ntoa(p->u.prefix4),
  187. CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
  188. "secondary" : "primary");
  189. }
  190. }
  191. #endif
  192. static int pim_zebra_if_address_add(int command, struct zclient *zclient,
  193. zebra_size_t length, vrf_id_t vrf_id)
  194. {
  195. struct connected *c;
  196. struct prefix *p;
  197. zassert(command == ZEBRA_INTERFACE_ADDRESS_ADD);
  198. /*
  199. zebra api notifies address adds/dels events by using the same call
  200. interface_add_read below, see comments in lib/zclient.c
  201. zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
  202. will add address to interface list by calling
  203. connected_add_by_prefix()
  204. */
  205. c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
  206. if (!c)
  207. return 0;
  208. p = c->address;
  209. if (p->family != AF_INET)
  210. return 0;
  211. if (PIM_DEBUG_ZEBRA) {
  212. char buf[BUFSIZ];
  213. prefix2str(p, buf, BUFSIZ);
  214. zlog_debug("%s: %s connected IP address %s flags %u %s",
  215. __PRETTY_FUNCTION__,
  216. c->ifp->name, buf, c->flags,
  217. CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
  218. #ifdef PIM_DEBUG_IFADDR_DUMP
  219. dump_if_address(c->ifp);
  220. #endif
  221. }
  222. if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
  223. /* trying to add primary address */
  224. struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
  225. if (primary_addr.s_addr != p->u.prefix4.s_addr) {
  226. /* but we had a primary address already */
  227. char buf[BUFSIZ];
  228. char old[100];
  229. prefix2str(p, buf, BUFSIZ);
  230. pim_inet4_dump("<old?>", primary_addr, old, sizeof(old));
  231. zlog_warn("%s: %s primary addr old=%s: forcing secondary flag on new=%s",
  232. __PRETTY_FUNCTION__,
  233. c->ifp->name, old, buf);
  234. SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
  235. }
  236. }
  237. pim_if_addr_add(c);
  238. return 0;
  239. }
  240. static int pim_zebra_if_address_del(int command, struct zclient *client,
  241. zebra_size_t length, vrf_id_t vrf_id)
  242. {
  243. struct connected *c;
  244. struct prefix *p;
  245. zassert(command == ZEBRA_INTERFACE_ADDRESS_DELETE);
  246. /*
  247. zebra api notifies address adds/dels events by using the same call
  248. interface_add_read below, see comments in lib/zclient.c
  249. zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
  250. will remove address from interface list by calling
  251. connected_delete_by_prefix()
  252. */
  253. c = zebra_interface_address_read(command, client->ibuf, vrf_id);
  254. if (!c)
  255. return 0;
  256. p = c->address;
  257. if (p->family != AF_INET)
  258. return 0;
  259. if (PIM_DEBUG_ZEBRA) {
  260. char buf[BUFSIZ];
  261. prefix2str(p, buf, BUFSIZ);
  262. zlog_debug("%s: %s disconnected IP address %s flags %u %s",
  263. __PRETTY_FUNCTION__,
  264. c->ifp->name, buf, c->flags,
  265. CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
  266. #ifdef PIM_DEBUG_IFADDR_DUMP
  267. dump_if_address(c->ifp);
  268. #endif
  269. }
  270. pim_if_addr_del(c, 0);
  271. return 0;
  272. }
  273. static void scan_upstream_rpf_cache()
  274. {
  275. struct listnode *up_node;
  276. struct listnode *up_nextnode;
  277. struct pim_upstream *up;
  278. for (ALL_LIST_ELEMENTS(qpim_upstream_list, up_node, up_nextnode, up)) {
  279. struct in_addr old_rpf_addr;
  280. enum pim_rpf_result rpf_result;
  281. rpf_result = pim_rpf_update(up, &old_rpf_addr);
  282. if (rpf_result == PIM_RPF_FAILURE)
  283. continue;
  284. if (rpf_result == PIM_RPF_CHANGED) {
  285. if (up->join_state == PIM_UPSTREAM_JOINED) {
  286. /*
  287. RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
  288. Transitions from Joined State
  289. RPF'(S,G) changes not due to an Assert
  290. The upstream (S,G) state machine remains in Joined
  291. state. Send Join(S,G) to the new upstream neighbor, which is
  292. the new value of RPF'(S,G). Send Prune(S,G) to the old
  293. upstream neighbor, which is the old value of RPF'(S,G). Set
  294. the Join Timer (JT) to expire after t_periodic seconds.
  295. */
  296. /* send Prune(S,G) to the old upstream neighbor */
  297. pim_joinprune_send(up->rpf.source_nexthop.interface,
  298. old_rpf_addr,
  299. up->source_addr,
  300. up->group_addr,
  301. 0 /* prune */);
  302. /* send Join(S,G) to the current upstream neighbor */
  303. pim_joinprune_send(up->rpf.source_nexthop.interface,
  304. up->rpf.rpf_addr,
  305. up->source_addr,
  306. up->group_addr,
  307. 1 /* join */);
  308. pim_upstream_join_timer_restart(up);
  309. } /* up->join_state == PIM_UPSTREAM_JOINED */
  310. /* FIXME can join_desired actually be changed by pim_rpf_update()
  311. returning PIM_RPF_CHANGED ? */
  312. pim_upstream_update_join_desired(up);
  313. } /* PIM_RPF_CHANGED */
  314. } /* for (qpim_upstream_list) */
  315. }
  316. void pim_scan_oil()
  317. {
  318. struct listnode *node;
  319. struct listnode *nextnode;
  320. struct channel_oil *c_oil;
  321. qpim_scan_oil_last = pim_time_monotonic_sec();
  322. ++qpim_scan_oil_events;
  323. for (ALL_LIST_ELEMENTS(qpim_channel_oil_list, node, nextnode, c_oil)) {
  324. int old_vif_index;
  325. int input_iface_vif_index = fib_lookup_if_vif_index(c_oil->oil.mfcc_origin);
  326. if (input_iface_vif_index < 1) {
  327. char source_str[100];
  328. char group_str[100];
  329. pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  330. pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  331. zlog_warn("%s %s: could not find input interface for (S,G)=(%s,%s)",
  332. __FILE__, __PRETTY_FUNCTION__,
  333. source_str, group_str);
  334. continue;
  335. }
  336. if (input_iface_vif_index == c_oil->oil.mfcc_parent) {
  337. /* RPF unchanged */
  338. continue;
  339. }
  340. if (PIM_DEBUG_ZEBRA) {
  341. struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
  342. struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
  343. char source_str[100];
  344. char group_str[100];
  345. pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  346. pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  347. zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
  348. __FILE__, __PRETTY_FUNCTION__,
  349. source_str, group_str,
  350. old_iif ? old_iif->name : "<old_iif?>", c_oil->oil.mfcc_parent,
  351. new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index);
  352. }
  353. /* new iif loops to existing oif ? */
  354. if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) {
  355. struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
  356. if (PIM_DEBUG_ZEBRA) {
  357. char source_str[100];
  358. char group_str[100];
  359. pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  360. pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  361. zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
  362. __FILE__, __PRETTY_FUNCTION__,
  363. source_str, group_str,
  364. new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index);
  365. }
  366. del_oif(c_oil, new_iif, PIM_OIF_FLAG_PROTO_ANY);
  367. }
  368. /* update iif vif_index */
  369. old_vif_index = c_oil->oil.mfcc_parent;
  370. c_oil->oil.mfcc_parent = input_iface_vif_index;
  371. /* update kernel multicast forwarding cache (MFC) */
  372. if (pim_mroute_add(&c_oil->oil)) {
  373. /* just log warning */
  374. struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index);
  375. struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index);
  376. char source_str[100];
  377. char group_str[100];
  378. pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  379. pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  380. zlog_warn("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
  381. __FILE__, __PRETTY_FUNCTION__,
  382. source_str, group_str,
  383. old_iif ? old_iif->name : "<old_iif?>", c_oil->oil.mfcc_parent,
  384. new_iif ? new_iif->name : "<new_iif?>", input_iface_vif_index);
  385. continue;
  386. }
  387. } /* for (qpim_channel_oil_list) */
  388. }
  389. static int on_rpf_cache_refresh(struct thread *t)
  390. {
  391. zassert(t);
  392. zassert(qpim_rpf_cache_refresher);
  393. qpim_rpf_cache_refresher = 0;
  394. /* update PIM protocol state */
  395. scan_upstream_rpf_cache();
  396. /* update kernel multicast forwarding cache (MFC) */
  397. pim_scan_oil();
  398. qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
  399. ++qpim_rpf_cache_refresh_events;
  400. return 0;
  401. }
  402. static void sched_rpf_cache_refresh()
  403. {
  404. ++qpim_rpf_cache_refresh_requests;
  405. if (qpim_rpf_cache_refresher) {
  406. /* Refresh timer is already running */
  407. return;
  408. }
  409. /* Start refresh timer */
  410. if (PIM_DEBUG_ZEBRA) {
  411. zlog_debug("%s: triggering %ld msec timer",
  412. __PRETTY_FUNCTION__,
  413. qpim_rpf_cache_refresh_delay_msec);
  414. }
  415. THREAD_TIMER_MSEC_ON(master, qpim_rpf_cache_refresher,
  416. on_rpf_cache_refresh,
  417. 0, qpim_rpf_cache_refresh_delay_msec);
  418. }
  419. static int redist_read_ipv4_route(int command, struct zclient *zclient,
  420. zebra_size_t length, vrf_id_t vrf_id)
  421. {
  422. struct stream *s;
  423. struct zapi_ipv4 api;
  424. unsigned long ifindex;
  425. struct in_addr nexthop;
  426. struct prefix_ipv4 p;
  427. int min_len = 4;
  428. if (length < min_len) {
  429. zlog_warn("%s %s: short buffer: length=%d min=%d",
  430. __FILE__, __PRETTY_FUNCTION__,
  431. length, min_len);
  432. return -1;
  433. }
  434. s = zclient->ibuf;
  435. ifindex = 0;
  436. nexthop.s_addr = 0;
  437. /* Type, flags, message. */
  438. api.type = stream_getc(s);
  439. api.flags = stream_getc(s);
  440. api.message = stream_getc(s);
  441. /* IPv4 prefix length. */
  442. memset(&p, 0, sizeof(struct prefix_ipv4));
  443. p.family = AF_INET;
  444. p.prefixlen = stream_getc(s);
  445. min_len +=
  446. PSIZE(p.prefixlen) +
  447. CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? 5 : 0 +
  448. CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? 5 : 0 +
  449. CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? 1 : 0 +
  450. CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? 4 : 0;
  451. if (PIM_DEBUG_ZEBRA) {
  452. zlog_debug("%s %s: length=%d min_len=%d flags=%s%s%s%s",
  453. __FILE__, __PRETTY_FUNCTION__,
  454. length, min_len,
  455. CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "",
  456. CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "",
  457. CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "",
  458. CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : "");
  459. }
  460. if (length < min_len) {
  461. zlog_warn("%s %s: short buffer: length=%d min_len=%d flags=%s%s%s%s",
  462. __FILE__, __PRETTY_FUNCTION__,
  463. length, min_len,
  464. CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "",
  465. CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "",
  466. CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "",
  467. CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : "");
  468. return -1;
  469. }
  470. /* IPv4 prefix. */
  471. stream_get(&p.prefix, s, PSIZE(p.prefixlen));
  472. /* Nexthop, ifindex, distance, metric. */
  473. if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
  474. api.nexthop_num = stream_getc(s);
  475. nexthop.s_addr = stream_get_ipv4(s);
  476. }
  477. if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) {
  478. api.ifindex_num = stream_getc(s);
  479. ifindex = stream_getl(s);
  480. }
  481. api.distance = CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ?
  482. stream_getc(s) :
  483. 0;
  484. api.metric = CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ?
  485. stream_getl(s) :
  486. 0;
  487. switch (command) {
  488. case ZEBRA_IPV4_ROUTE_ADD:
  489. if (PIM_DEBUG_ZEBRA) {
  490. char buf[2][INET_ADDRSTRLEN];
  491. zlog_debug("%s: add %s %s/%d "
  492. "nexthop %s ifindex %ld metric%s %u distance%s %u",
  493. __PRETTY_FUNCTION__,
  494. zebra_route_string(api.type),
  495. inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
  496. p.prefixlen,
  497. inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
  498. ifindex,
  499. CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss",
  500. api.metric,
  501. CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss",
  502. api.distance);
  503. }
  504. break;
  505. case ZEBRA_IPV4_ROUTE_DELETE:
  506. if (PIM_DEBUG_ZEBRA) {
  507. char buf[2][INET_ADDRSTRLEN];
  508. zlog_debug("%s: delete %s %s/%d "
  509. "nexthop %s ifindex %ld metric%s %u distance%s %u",
  510. __PRETTY_FUNCTION__,
  511. zebra_route_string(api.type),
  512. inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
  513. p.prefixlen,
  514. inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])),
  515. ifindex,
  516. CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss",
  517. api.metric,
  518. CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss",
  519. api.distance);
  520. }
  521. break;
  522. default:
  523. zlog_warn("%s: unknown command=%d", __PRETTY_FUNCTION__, command);
  524. return -1;
  525. }
  526. sched_rpf_cache_refresh();
  527. return 0;
  528. }
  529. static void pim_zebra_connected(struct zclient *zclient)
  530. {
  531. zclient_send_requests(zclient, VRF_DEFAULT);
  532. }
  533. void pim_zebra_init(char *zebra_sock_path)
  534. {
  535. int i;
  536. if (zebra_sock_path)
  537. zclient_serv_path_set(zebra_sock_path);
  538. #ifdef HAVE_TCP_ZEBRA
  539. zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT);
  540. #else
  541. zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get());
  542. #endif
  543. /* Socket for receiving updates from Zebra daemon */
  544. qpim_zclient_update = zclient_new();
  545. qpim_zclient_update->zebra_connected = pim_zebra_connected;
  546. qpim_zclient_update->router_id_update = pim_router_id_update_zebra;
  547. qpim_zclient_update->interface_add = pim_zebra_if_add;
  548. qpim_zclient_update->interface_delete = pim_zebra_if_del;
  549. qpim_zclient_update->interface_up = pim_zebra_if_state_up;
  550. qpim_zclient_update->interface_down = pim_zebra_if_state_down;
  551. qpim_zclient_update->interface_address_add = pim_zebra_if_address_add;
  552. qpim_zclient_update->interface_address_delete = pim_zebra_if_address_del;
  553. qpim_zclient_update->ipv4_route_add = redist_read_ipv4_route;
  554. qpim_zclient_update->ipv4_route_delete = redist_read_ipv4_route;
  555. zclient_init(qpim_zclient_update, ZEBRA_ROUTE_PIM);
  556. if (PIM_DEBUG_PIM_TRACE) {
  557. zlog_info("zclient_init cleared redistribution request");
  558. }
  559. zassert(qpim_zclient_update->redist_default == ZEBRA_ROUTE_PIM);
  560. /* Request all redistribution */
  561. for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
  562. if (i == qpim_zclient_update->redist_default)
  563. continue;
  564. vrf_bitmap_set(qpim_zclient_update->redist[i], VRF_DEFAULT);
  565. if (PIM_DEBUG_PIM_TRACE) {
  566. zlog_debug("%s: requesting redistribution for %s (%i)",
  567. __PRETTY_FUNCTION__, zebra_route_string(i), i);
  568. }
  569. }
  570. /* Request default information */
  571. vrf_bitmap_set(qpim_zclient_update->default_information, VRF_DEFAULT);
  572. if (PIM_DEBUG_PIM_TRACE) {
  573. zlog_info("%s: requesting default information redistribution",
  574. __PRETTY_FUNCTION__);
  575. zlog_notice("%s: zclient update socket initialized",
  576. __PRETTY_FUNCTION__);
  577. }
  578. zassert(!qpim_zclient_lookup);
  579. qpim_zclient_lookup = zclient_lookup_new();
  580. zassert(qpim_zclient_lookup);
  581. }
  582. void igmp_anysource_forward_start(struct igmp_group *group)
  583. {
  584. /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
  585. zassert(group->group_filtermode_isexcl);
  586. zassert(listcount(group->group_source_list) < 1);
  587. if (PIM_DEBUG_IGMP_TRACE) {
  588. zlog_debug("%s %s: UNIMPLEMENTED",
  589. __FILE__, __PRETTY_FUNCTION__);
  590. }
  591. }
  592. void igmp_anysource_forward_stop(struct igmp_group *group)
  593. {
  594. /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
  595. zassert((!group->group_filtermode_isexcl) || (listcount(group->group_source_list) > 0));
  596. if (PIM_DEBUG_IGMP_TRACE) {
  597. zlog_debug("%s %s: UNIMPLEMENTED",
  598. __FILE__, __PRETTY_FUNCTION__);
  599. }
  600. }
  601. static int fib_lookup_if_vif_index(struct in_addr addr)
  602. {
  603. struct pim_zlookup_nexthop nexthop_tab[PIM_NEXTHOP_IFINDEX_TAB_SIZE];
  604. int num_ifindex;
  605. int vif_index;
  606. int first_ifindex;
  607. num_ifindex = zclient_lookup_nexthop(qpim_zclient_lookup, nexthop_tab,
  608. PIM_NEXTHOP_IFINDEX_TAB_SIZE, addr,
  609. PIM_NEXTHOP_LOOKUP_MAX);
  610. if (num_ifindex < 1) {
  611. char addr_str[100];
  612. pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
  613. zlog_warn("%s %s: could not find nexthop ifindex for address %s",
  614. __FILE__, __PRETTY_FUNCTION__,
  615. addr_str);
  616. return -1;
  617. }
  618. first_ifindex = nexthop_tab[0].ifindex;
  619. if (num_ifindex > 1) {
  620. char addr_str[100];
  621. pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
  622. zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
  623. __FILE__, __PRETTY_FUNCTION__,
  624. num_ifindex, addr_str, first_ifindex);
  625. /* debug warning only, do not return */
  626. }
  627. if (PIM_DEBUG_ZEBRA) {
  628. char addr_str[100];
  629. pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
  630. zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
  631. __FILE__, __PRETTY_FUNCTION__,
  632. first_ifindex, ifindex2ifname(first_ifindex), addr_str);
  633. }
  634. vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex);
  635. if (vif_index < 1) {
  636. char addr_str[100];
  637. pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
  638. zlog_warn("%s %s: low vif_index=%d < 1 nexthop for address %s",
  639. __FILE__, __PRETTY_FUNCTION__,
  640. vif_index, addr_str);
  641. return -2;
  642. }
  643. zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS);
  644. if (vif_index > qpim_mroute_oif_highest_vif_index) {
  645. char addr_str[100];
  646. pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
  647. zlog_warn("%s %s: high vif_index=%d > highest_vif_index=%d nexthop for address %s",
  648. __FILE__, __PRETTY_FUNCTION__,
  649. vif_index, qpim_mroute_oif_highest_vif_index, addr_str);
  650. zlog_warn("%s %s: pim disabled on interface %s vif_index=%d ?",
  651. __FILE__, __PRETTY_FUNCTION__,
  652. ifindex2ifname(vif_index),
  653. vif_index);
  654. return -3;
  655. }
  656. return vif_index;
  657. }
  658. static int add_oif(struct channel_oil *channel_oil,
  659. struct interface *oif,
  660. uint32_t proto_mask)
  661. {
  662. struct pim_interface *pim_ifp;
  663. int old_ttl;
  664. zassert(channel_oil);
  665. pim_ifp = oif->info;
  666. if (PIM_DEBUG_MROUTE) {
  667. char group_str[100];
  668. char source_str[100];
  669. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  670. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  671. zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
  672. __FILE__, __PRETTY_FUNCTION__,
  673. source_str, group_str,
  674. proto_mask, oif->name, pim_ifp->mroute_vif_index);
  675. }
  676. if (pim_ifp->mroute_vif_index < 1) {
  677. zlog_warn("%s %s: interface %s vif_index=%d < 1",
  678. __FILE__, __PRETTY_FUNCTION__,
  679. oif->name, pim_ifp->mroute_vif_index);
  680. return -1;
  681. }
  682. #ifdef PIM_ENFORCE_LOOPFREE_MFC
  683. /*
  684. Prevent creating MFC entry with OIF=IIF.
  685. This is a protection against implementation mistakes.
  686. PIM protocol implicitely ensures loopfree multicast topology.
  687. IGMP must be protected against adding looped MFC entries created
  688. by both source and receiver attached to the same interface. See
  689. TODO T22.
  690. */
  691. if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) {
  692. char group_str[100];
  693. char source_str[100];
  694. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  695. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  696. zlog_warn("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
  697. __FILE__, __PRETTY_FUNCTION__,
  698. proto_mask, oif->name, pim_ifp->mroute_vif_index,
  699. source_str, group_str);
  700. return -2;
  701. }
  702. #endif
  703. zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS);
  704. zassert(pim_ifp->mroute_vif_index <= qpim_mroute_oif_highest_vif_index);
  705. /* Prevent single protocol from subscribing same interface to
  706. channel (S,G) multiple times */
  707. if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) {
  708. char group_str[100];
  709. char source_str[100];
  710. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  711. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  712. zlog_warn("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
  713. __FILE__, __PRETTY_FUNCTION__,
  714. proto_mask, oif->name, pim_ifp->mroute_vif_index,
  715. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
  716. source_str, group_str);
  717. return -3;
  718. }
  719. /* Allow other protocol to request subscription of same interface to
  720. channel (S,G) multiple times, by silently ignoring further
  721. requests */
  722. if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
  723. /* Check the OIF really exists before returning, and only log
  724. warning otherwise */
  725. if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
  726. char group_str[100];
  727. char source_str[100];
  728. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  729. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  730. zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)",
  731. __FILE__, __PRETTY_FUNCTION__,
  732. proto_mask, oif->name, pim_ifp->mroute_vif_index,
  733. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
  734. source_str, group_str);
  735. }
  736. return 0;
  737. }
  738. old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
  739. if (old_ttl > 0) {
  740. char group_str[100];
  741. char source_str[100];
  742. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  743. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  744. zlog_warn("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)",
  745. __FILE__, __PRETTY_FUNCTION__,
  746. oif->name, pim_ifp->mroute_vif_index,
  747. source_str, group_str);
  748. return -4;
  749. }
  750. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL;
  751. if (pim_mroute_add(&channel_oil->oil)) {
  752. char group_str[100];
  753. char source_str[100];
  754. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  755. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  756. zlog_warn("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)",
  757. __FILE__, __PRETTY_FUNCTION__,
  758. oif->name, pim_ifp->mroute_vif_index,
  759. source_str, group_str);
  760. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
  761. return -5;
  762. }
  763. channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec();
  764. ++channel_oil->oil_size;
  765. channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
  766. if (PIM_DEBUG_MROUTE) {
  767. char group_str[100];
  768. char source_str[100];
  769. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  770. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  771. zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
  772. __FILE__, __PRETTY_FUNCTION__,
  773. source_str, group_str,
  774. proto_mask, oif->name, pim_ifp->mroute_vif_index);
  775. }
  776. return 0;
  777. }
  778. static int del_oif(struct channel_oil *channel_oil,
  779. struct interface *oif,
  780. uint32_t proto_mask)
  781. {
  782. struct pim_interface *pim_ifp;
  783. int old_ttl;
  784. zassert(channel_oil);
  785. pim_ifp = oif->info;
  786. zassert(pim_ifp->mroute_vif_index >= 1);
  787. zassert(qpim_mroute_oif_highest_vif_index < MAXVIFS);
  788. zassert(pim_ifp->mroute_vif_index <= qpim_mroute_oif_highest_vif_index);
  789. if (PIM_DEBUG_MROUTE) {
  790. char group_str[100];
  791. char source_str[100];
  792. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  793. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  794. zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
  795. __FILE__, __PRETTY_FUNCTION__,
  796. source_str, group_str,
  797. proto_mask, oif->name, pim_ifp->mroute_vif_index);
  798. }
  799. /* Prevent single protocol from unsubscribing same interface from
  800. channel (S,G) multiple times */
  801. if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) {
  802. char group_str[100];
  803. char source_str[100];
  804. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  805. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  806. zlog_warn("%s %s: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
  807. __FILE__, __PRETTY_FUNCTION__,
  808. proto_mask, oif->name, pim_ifp->mroute_vif_index,
  809. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
  810. source_str, group_str);
  811. return -2;
  812. }
  813. /* Mark that protocol is no longer interested in this OIF */
  814. channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask;
  815. /* Allow multiple protocols to unsubscribe same interface from
  816. channel (S,G) multiple times, by silently ignoring requests while
  817. there is at least one protocol interested in the channel */
  818. if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
  819. /* Check the OIF keeps existing before returning, and only log
  820. warning otherwise */
  821. if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
  822. char group_str[100];
  823. char source_str[100];
  824. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  825. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  826. zlog_warn("%s %s: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
  827. __FILE__, __PRETTY_FUNCTION__,
  828. proto_mask, oif->name, pim_ifp->mroute_vif_index,
  829. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
  830. source_str, group_str);
  831. }
  832. return 0;
  833. }
  834. old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
  835. if (old_ttl < 1) {
  836. char group_str[100];
  837. char source_str[100];
  838. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  839. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  840. zlog_warn("%s %s: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)",
  841. __FILE__, __PRETTY_FUNCTION__,
  842. oif->name, pim_ifp->mroute_vif_index,
  843. source_str, group_str);
  844. return -3;
  845. }
  846. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
  847. if (pim_mroute_add(&channel_oil->oil)) {
  848. char group_str[100];
  849. char source_str[100];
  850. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  851. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  852. zlog_warn("%s %s: could not remove output interface %s (vif_index=%d) from channel (S,G)=(%s,%s)",
  853. __FILE__, __PRETTY_FUNCTION__,
  854. oif->name, pim_ifp->mroute_vif_index,
  855. source_str, group_str);
  856. channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
  857. return -4;
  858. }
  859. --channel_oil->oil_size;
  860. if (channel_oil->oil_size < 1) {
  861. if (pim_mroute_del(&channel_oil->oil)) {
  862. /* just log a warning in case of failure */
  863. char group_str[100];
  864. char source_str[100];
  865. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  866. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  867. zlog_warn("%s %s: failure removing OIL for channel (S,G)=(%s,%s)",
  868. __FILE__, __PRETTY_FUNCTION__,
  869. source_str, group_str);
  870. }
  871. }
  872. if (PIM_DEBUG_MROUTE) {
  873. char group_str[100];
  874. char source_str[100];
  875. pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
  876. pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
  877. zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
  878. __FILE__, __PRETTY_FUNCTION__,
  879. source_str, group_str,
  880. proto_mask, oif->name, pim_ifp->mroute_vif_index);
  881. }
  882. return 0;
  883. }
  884. void igmp_source_forward_start(struct igmp_source *source)
  885. {
  886. struct igmp_group *group;
  887. int result;
  888. if (PIM_DEBUG_IGMP_TRACE) {
  889. char source_str[100];
  890. char group_str[100];
  891. pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
  892. pim_inet4_dump("<group?>", source->source_group->group_addr, group_str, sizeof(group_str));
  893. zlog_debug("%s: (S,G)=(%s,%s) igmp_sock=%d oif=%s fwd=%d",
  894. __PRETTY_FUNCTION__,
  895. source_str, group_str,
  896. source->source_group->group_igmp_sock->fd,
  897. source->source_group->group_igmp_sock->interface->name,
  898. IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
  899. }
  900. /* Prevent IGMP interface from installing multicast route multiple
  901. times */
  902. if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
  903. return;
  904. }
  905. group = source->source_group;
  906. if (!source->source_channel_oil) {
  907. struct pim_interface *pim_oif;
  908. int input_iface_vif_index = fib_lookup_if_vif_index(source->source_addr);
  909. if (input_iface_vif_index < 1) {
  910. char source_str[100];
  911. pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
  912. zlog_warn("%s %s: could not find input interface for source %s",
  913. __FILE__, __PRETTY_FUNCTION__,
  914. source_str);
  915. return;
  916. }
  917. /*
  918. Protect IGMP against adding looped MFC entries created by both
  919. source and receiver attached to the same interface. See TODO
  920. T22.
  921. */
  922. pim_oif = source->source_group->group_igmp_sock->interface->info;
  923. if (!pim_oif) {
  924. zlog_warn("%s: multicast not enabled on oif=%s ?",
  925. __PRETTY_FUNCTION__,
  926. source->source_group->group_igmp_sock->interface->name);
  927. return;
  928. }
  929. if (pim_oif->mroute_vif_index < 1) {
  930. zlog_warn("%s %s: oif=%s vif_index=%d < 1",
  931. __FILE__, __PRETTY_FUNCTION__,
  932. source->source_group->group_igmp_sock->interface->name,
  933. pim_oif->mroute_vif_index);
  934. return;
  935. }
  936. if (input_iface_vif_index == pim_oif->mroute_vif_index) {
  937. /* ignore request for looped MFC entry */
  938. if (PIM_DEBUG_IGMP_TRACE) {
  939. char source_str[100];
  940. char group_str[100];
  941. pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
  942. pim_inet4_dump("<group?>", source->source_group->group_addr, group_str, sizeof(group_str));
  943. zlog_debug("%s: ignoring request for looped MFC entry (S,G)=(%s,%s): igmp_sock=%d oif=%s vif_index=%d",
  944. __PRETTY_FUNCTION__,
  945. source_str, group_str,
  946. source->source_group->group_igmp_sock->fd,
  947. source->source_group->group_igmp_sock->interface->name,
  948. input_iface_vif_index);
  949. }
  950. return;
  951. }
  952. source->source_channel_oil = pim_channel_oil_add(group->group_addr,
  953. source->source_addr,
  954. input_iface_vif_index);
  955. if (!source->source_channel_oil) {
  956. char group_str[100];
  957. char source_str[100];
  958. pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
  959. pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
  960. zlog_warn("%s %s: could not create OIL for channel (S,G)=(%s,%s)",
  961. __FILE__, __PRETTY_FUNCTION__,
  962. source_str, group_str);
  963. return;
  964. }
  965. }
  966. result = add_oif(source->source_channel_oil,
  967. group->group_igmp_sock->interface,
  968. PIM_OIF_FLAG_PROTO_IGMP);
  969. if (result) {
  970. zlog_warn("%s: add_oif() failed with return=%d",
  971. __func__, result);
  972. return;
  973. }
  974. /*
  975. Feed IGMPv3-gathered local membership information into PIM
  976. per-interface (S,G) state.
  977. */
  978. pim_ifchannel_local_membership_add(group->group_igmp_sock->interface,
  979. source->source_addr, group->group_addr);
  980. IGMP_SOURCE_DO_FORWARDING(source->source_flags);
  981. }
  982. /*
  983. igmp_source_forward_stop: stop fowarding, but keep the source
  984. igmp_source_delete: stop fowarding, and delete the source
  985. */
  986. void igmp_source_forward_stop(struct igmp_source *source)
  987. {
  988. struct igmp_group *group;
  989. int result;
  990. if (PIM_DEBUG_IGMP_TRACE) {
  991. char source_str[100];
  992. char group_str[100];
  993. pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
  994. pim_inet4_dump("<group?>", source->source_group->group_addr, group_str, sizeof(group_str));
  995. zlog_debug("%s: (S,G)=(%s,%s) igmp_sock=%d oif=%s fwd=%d",
  996. __PRETTY_FUNCTION__,
  997. source_str, group_str,
  998. source->source_group->group_igmp_sock->fd,
  999. source->source_group->group_igmp_sock->interface->name,
  1000. IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
  1001. }
  1002. /* Prevent IGMP interface from removing multicast route multiple
  1003. times */
  1004. if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
  1005. return;
  1006. }
  1007. group = source->source_group;
  1008. /*
  1009. It appears that in certain circumstances that
  1010. igmp_source_forward_stop is called when IGMP forwarding
  1011. was not enabled in oif_flags for this outgoing interface.
  1012. Possibly because of multiple calls. When that happens, we
  1013. enter the below if statement and this function returns early
  1014. which in turn triggers the calling function to assert.
  1015. Making the call to del_oif and ignoring the return code
  1016. fixes the issue without ill effect, similar to
  1017. pim_forward_stop below.
  1018. */
  1019. result = del_oif(source->source_channel_oil,
  1020. group->group_igmp_sock->interface,
  1021. PIM_OIF_FLAG_PROTO_IGMP);
  1022. if (result) {
  1023. zlog_warn("%s: del_oif() failed with return=%d",
  1024. __func__, result);
  1025. return;
  1026. }
  1027. /*
  1028. Feed IGMPv3-gathered local membership information into PIM
  1029. per-interface (S,G) state.
  1030. */
  1031. pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
  1032. source->source_addr, group->group_addr);
  1033. IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
  1034. }
  1035. void pim_forward_start(struct pim_ifchannel *ch)
  1036. {
  1037. struct pim_upstream *up = ch->upstream;
  1038. if (PIM_DEBUG_PIM_TRACE) {
  1039. char source_str[100];
  1040. char group_str[100];
  1041. pim_inet4_dump("<source?>", ch->source_addr, source_str, sizeof(source_str));
  1042. pim_inet4_dump("<group?>", ch->group_addr, group_str, sizeof(group_str));
  1043. zlog_debug("%s: (S,G)=(%s,%s) oif=%s",
  1044. __PRETTY_FUNCTION__,
  1045. source_str, group_str, ch->interface->name);
  1046. }
  1047. if (!up->channel_oil) {
  1048. int input_iface_vif_index = fib_lookup_if_vif_index(up->source_addr);
  1049. if (input_iface_vif_index < 1) {
  1050. char source_str[100];
  1051. pim_inet4_dump("<source?>", up->source_addr, source_str, sizeof(source_str));
  1052. zlog_warn("%s %s: could not find input interface for source %s",
  1053. __FILE__, __PRETTY_FUNCTION__,
  1054. source_str);
  1055. return;
  1056. }
  1057. up->channel_oil = pim_channel_oil_add(up->group_addr, up->source_addr,
  1058. input_iface_vif_index);
  1059. if (!up->channel_oil) {
  1060. char group_str[100];
  1061. char source_str[100];
  1062. pim_inet4_dump("<group?>", up->group_addr, group_str, sizeof(group_str));
  1063. pim_inet4_dump("<source?>", up->source_addr, source_str, sizeof(source_str));
  1064. zlog_warn("%s %s: could not create OIL for channel (S,G)=(%s,%s)",
  1065. __FILE__, __PRETTY_FUNCTION__,
  1066. source_str, group_str);
  1067. return;
  1068. }
  1069. }
  1070. add_oif(up->channel_oil,
  1071. ch->interface,
  1072. PIM_OIF_FLAG_PROTO_PIM);
  1073. }
  1074. void pim_forward_stop(struct pim_ifchannel *ch)
  1075. {
  1076. struct pim_upstream *up = ch->upstream;
  1077. if (PIM_DEBUG_PIM_TRACE) {
  1078. char source_str[100];
  1079. char group_str[100];
  1080. pim_inet4_dump("<source?>", ch->source_addr, source_str, sizeof(source_str));
  1081. pim_inet4_dump("<group?>", ch->group_addr, group_str, sizeof(group_str));
  1082. zlog_debug("%s: (S,G)=(%s,%s) oif=%s",
  1083. __PRETTY_FUNCTION__,
  1084. source_str, group_str, ch->interface->name);
  1085. }
  1086. if (!up->channel_oil) {
  1087. char source_str[100];
  1088. char group_str[100];
  1089. pim_inet4_dump("<source?>", ch->source_addr, source_str, sizeof(source_str));
  1090. pim_inet4_dump("<group?>", ch->group_addr, group_str, sizeof(group_str));
  1091. zlog_warn("%s: (S,G)=(%s,%s) oif=%s missing channel OIL",
  1092. __PRETTY_FUNCTION__,
  1093. source_str, group_str, ch->interface->name);
  1094. return;
  1095. }
  1096. del_oif(up->channel_oil,
  1097. ch->interface,
  1098. PIM_OIF_FLAG_PROTO_PIM);
  1099. }