3 * Copyright (C) 2017 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "pimd/pim_nht.h"
34 #include "pim_ifchannel.h"
35 #include "pim_mroute.h"
36 #include "pim_zebra.h"
37 #include "pim_upstream.h"
39 #include "pim_jp_agg.h"
40 #include "pim_zebra.h"
41 #include "pim_zlookup.h"
44 * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
48 pim_sendmsg_zebra_rnh (struct zclient
*zclient
, struct pim_nexthop_cache
*pnc
,
56 if (!zclient
|| zclient
->sock
< 0)
59 p
= &(pnc
->rpf
.rpf_addr
);
62 zclient_create_header (s
, command
, VRF_DEFAULT
);
63 /* get update for all routes for a prefix */
66 stream_putw (s
, PREFIX_FAMILY (p
));
67 stream_putc (s
, p
->prefixlen
);
68 switch (PREFIX_FAMILY (p
))
71 stream_put_in_addr (s
, &p
->u
.prefix4
);
74 stream_put (s
, &(p
->u
.prefix6
), 16);
79 stream_putw_at (s
, 0, stream_get_endp (s
));
81 ret
= zclient_send_message (zclient
);
83 zlog_warn ("sendmsg_nexthop: zclient_send_message() failed");
88 char buf
[PREFIX2STR_BUFFER
];
89 prefix2str (p
, buf
, sizeof (buf
));
90 zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ",
92 (command
== ZEBRA_NEXTHOP_REGISTER
) ? " " : "de", buf
, ret
);
98 struct pim_nexthop_cache
*
99 pim_nexthop_cache_find (struct pim_rpf
*rpf
)
101 struct pim_nexthop_cache
*pnc
= NULL
;
102 struct pim_nexthop_cache lookup
;
104 lookup
.rpf
.rpf_addr
.family
= rpf
->rpf_addr
.family
;
105 lookup
.rpf
.rpf_addr
.prefixlen
= rpf
->rpf_addr
.prefixlen
;
106 lookup
.rpf
.rpf_addr
.u
.prefix4
.s_addr
= rpf
->rpf_addr
.u
.prefix4
.s_addr
;
108 pnc
= hash_lookup (pimg
->rpf_hash
, &lookup
);
114 struct pim_nexthop_cache
*
115 pim_nexthop_cache_add (struct pim_rpf
*rpf_addr
)
117 struct pim_nexthop_cache
*pnc
;
119 pnc
= XCALLOC (MTYPE_PIM_NEXTHOP_CACHE
, sizeof (struct pim_nexthop_cache
));
122 zlog_err ("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__
);
125 pnc
->rpf
.rpf_addr
.family
= rpf_addr
->rpf_addr
.family
;
126 pnc
->rpf
.rpf_addr
.prefixlen
= rpf_addr
->rpf_addr
.prefixlen
;
127 pnc
->rpf
.rpf_addr
.u
.prefix4
.s_addr
= rpf_addr
->rpf_addr
.u
.prefix4
.s_addr
;
129 pnc
= hash_get (pimg
->rpf_hash
, pnc
, hash_alloc_intern
);
131 pnc
->rp_list
= list_new ();
132 pnc
->rp_list
->cmp
= pim_rp_list_cmp
;
134 pnc
->upstream_list
= list_new ();
135 pnc
->upstream_list
->cmp
= pim_upstream_compare
;
139 char rpf_str
[PREFIX_STRLEN
];
140 pim_addr_dump ("<nht?>", &rpf_addr
->rpf_addr
, rpf_str
,
142 zlog_debug ("%s: NHT hash node, RP and UP lists allocated for %s ",
143 __PRETTY_FUNCTION__
, rpf_str
);
149 /* This API is used to Register an address with Zebra
150 ret 1 means nexthop cache is found.
153 pim_find_or_track_nexthop (struct prefix
*addr
, struct pim_upstream
*up
,
155 struct pim_nexthop_cache
*out_pnc
)
157 struct pim_nexthop_cache
*pnc
= NULL
;
159 struct listnode
*ch_node
= NULL
;
160 struct zclient
*zclient
= NULL
;
162 zclient
= pim_zebra_zclient_get ();
163 memset (&rpf
, 0, sizeof (struct pim_rpf
));
164 rpf
.rpf_addr
.family
= addr
->family
;
165 rpf
.rpf_addr
.prefixlen
= addr
->prefixlen
;
166 rpf
.rpf_addr
.u
.prefix4
= addr
->u
.prefix4
;
168 pnc
= pim_nexthop_cache_find (&rpf
);
171 pnc
= pim_nexthop_cache_add (&rpf
);
173 pim_sendmsg_zebra_rnh (zclient
, pnc
, ZEBRA_NEXTHOP_REGISTER
);
176 char rpf_str
[PREFIX_STRLEN
];
177 pim_addr_dump ("<nht-pnc?>", addr
, rpf_str
, sizeof (rpf_str
));
178 zlog_warn ("%s: pnc node allocation failed. addr %s ",
179 __PRETTY_FUNCTION__
, rpf_str
);
186 ch_node
= listnode_lookup (pnc
->rp_list
, rp
);
191 char rp_str
[PREFIX_STRLEN
];
192 pim_addr_dump ("<rp?>", &rp
->rp
.rpf_addr
, rp_str
,
194 zlog_debug ("%s: Add RP %s node to pnc cached list",
195 __PRETTY_FUNCTION__
, rp_str
);
197 listnode_add_sort (pnc
->rp_list
, rp
);
203 ch_node
= listnode_lookup (pnc
->upstream_list
, up
);
208 char buf
[PREFIX2STR_BUFFER
];
209 prefix2str (addr
, buf
, sizeof (buf
));
210 zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s",
211 __PRETTY_FUNCTION__
, up
->sg_str
, buf
);
213 listnode_add_sort (pnc
->upstream_list
, up
);
217 if (pnc
&& CHECK_FLAG (pnc
->flags
, PIM_NEXTHOP_VALID
))
219 memcpy (out_pnc
, pnc
, sizeof (struct pim_nexthop_cache
));
227 pim_delete_tracked_nexthop (struct prefix
*addr
, struct pim_upstream
*up
,
230 struct pim_nexthop_cache
*pnc
= NULL
;
231 struct pim_nexthop_cache lookup
;
232 struct zclient
*zclient
= NULL
;
234 zclient
= pim_zebra_zclient_get ();
236 /* Remove from RPF hash if it is the last entry */
237 lookup
.rpf
.rpf_addr
= *addr
;
238 pnc
= hash_lookup (pimg
->rpf_hash
, &lookup
);
242 listnode_delete (pnc
->rp_list
, rp
);
244 listnode_delete (pnc
->upstream_list
, up
);
247 zlog_debug ("%s: NHT rp_list count:%d upstream_list count:%d ",
248 __PRETTY_FUNCTION__
, pnc
->rp_list
->count
,
249 pnc
->upstream_list
->count
);
251 if (pnc
->rp_list
->count
== 0 && pnc
->upstream_list
->count
== 0)
253 pim_sendmsg_zebra_rnh (zclient
, pnc
, ZEBRA_NEXTHOP_UNREGISTER
);
255 list_delete (pnc
->rp_list
);
256 list_delete (pnc
->upstream_list
);
258 hash_release (pimg
->rpf_hash
, pnc
);
260 nexthops_free (pnc
->nexthop
);
261 XFREE (MTYPE_PIM_NEXTHOP_CACHE
, pnc
);
266 /* Update RP nexthop info based on Nexthop update received from Zebra.*/
268 pim_update_rp_nh (struct pim_nexthop_cache
*pnc
)
270 struct listnode
*node
= NULL
;
271 struct rp_info
*rp_info
= NULL
;
274 /*Traverse RP list and update each RP Nexthop info */
275 for (ALL_LIST_ELEMENTS_RO (pnc
->rp_list
, node
, rp_info
))
277 if (rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
== INADDR_NONE
)
280 //Compute PIM RPF using cached nexthop
281 ret
= pim_ecmp_nexthop_search (pnc
, &rp_info
->rp
.source_nexthop
,
282 &rp_info
->rp
.rpf_addr
, &rp_info
->group
, 1);
286 char rp_str
[PREFIX_STRLEN
];
287 pim_addr_dump ("<rp?>", &rp_info
->rp
.rpf_addr
, rp_str
,
289 zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ",
290 __PRETTY_FUNCTION__
, rp_str
,
291 rp_info
->rp
.source_nexthop
.interface
->name
);
301 /* This API is used to traverse nexthop cache of RPF addr
302 of upstream entry whose IPv4 nexthop address is in
303 unresolved state and due to event like pim neighbor
304 UP event if it can be resolved.
307 pim_resolve_upstream_nh (struct prefix
*nht_p
)
309 struct nexthop
*nh_node
= NULL
;
310 struct pim_nexthop_cache pnc
;
311 struct pim_neighbor
*nbr
= NULL
;
313 memset (&pnc
, 0, sizeof (struct pim_nexthop_cache
));
314 if ((pim_find_or_track_nexthop (nht_p
, NULL
, NULL
, &pnc
)) == 1)
316 for (nh_node
= pnc
.nexthop
; nh_node
; nh_node
= nh_node
->next
)
318 if (nh_node
->gate
.ipv4
.s_addr
== 0)
320 struct interface
*ifp1
= if_lookup_by_index(nh_node
->ifindex
,
322 nbr
= pim_neighbor_find_if (ifp1
);
325 nh_node
->gate
.ipv4
= nbr
->source_addr
;
328 char str
[PREFIX_STRLEN
];
329 char str1
[INET_ADDRSTRLEN
];
330 pim_inet4_dump ("<nht_nbr?>", nbr
->source_addr
, str1
,
332 pim_addr_dump ("<nht_addr?>", nht_p
, str
, sizeof (str
));
333 zlog_debug ("%s: addr %s new nexthop addr %s interface %s",
334 __PRETTY_FUNCTION__
, str
, str1
, ifp1
->name
);
342 /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/
344 pim_update_upstream_nh (struct pim_nexthop_cache
*pnc
)
346 struct listnode
*up_node
;
347 struct listnode
*ifnode
;
348 struct listnode
*up_nextnode
;
349 struct listnode
*node
;
350 struct pim_upstream
*up
= NULL
;
351 struct interface
*ifp
= NULL
;
354 for (ALL_LIST_ELEMENTS (pnc
->upstream_list
, up_node
, up_nextnode
, up
))
356 enum pim_rpf_result rpf_result
;
359 old
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
360 rpf_result
= pim_rpf_update (up
, &old
, 0);
361 if (rpf_result
== PIM_RPF_FAILURE
)
364 /* update kernel multicast forwarding cache (MFC) */
367 ifindex_t ifindex
= up
->rpf
.source_nexthop
.interface
->ifindex
;
368 vif_index
= pim_if_find_vifindex_by_ifindex (ifindex
);
369 /* Pass Current selected NH vif index to mroute download */
371 pim_scan_individual_oil (up
->channel_oil
, vif_index
);
375 zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid",
376 __PRETTY_FUNCTION__
, up
->sg_str
,
377 up
->rpf
.source_nexthop
.interface
->name
);
381 if (rpf_result
== PIM_RPF_CHANGED
)
383 struct pim_neighbor
*nbr
;
385 nbr
= pim_neighbor_find (old
.source_nexthop
.interface
,
386 old
.rpf_addr
.u
.prefix4
);
388 pim_jp_agg_remove_group (nbr
->upstream_jp_agg
, up
);
391 * We have detected a case where we might need to rescan
392 * the inherited o_list so do it.
394 if (up
->channel_oil
&& up
->channel_oil
->oil_inherited_rescan
)
396 pim_upstream_inherited_olist_decide (up
);
397 up
->channel_oil
->oil_inherited_rescan
= 0;
400 if (up
->join_state
== PIM_UPSTREAM_JOINED
)
403 * If we come up real fast we can be here
404 * where the mroute has not been installed
407 if (up
->channel_oil
&& !up
->channel_oil
->installed
)
408 pim_mroute_add (up
->channel_oil
, __PRETTY_FUNCTION__
);
411 RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
413 Transitions from Joined State
415 RPF'(S,G) changes not due to an Assert
417 The upstream (S,G) state machine remains in Joined
418 state. Send Join(S,G) to the new upstream neighbor, which is
419 the new value of RPF'(S,G). Send Prune(S,G) to the old
420 upstream neighbor, which is the old value of RPF'(S,G). Set
421 the Join Timer (JT) to expire after t_periodic seconds.
423 pim_jp_agg_switch_interface (&old
, &up
->rpf
, up
);
425 pim_upstream_join_timer_restart (up
, &old
);
426 } /* up->join_state == PIM_UPSTREAM_JOINED */
428 /* FIXME can join_desired actually be changed by pim_rpf_update()
429 returning PIM_RPF_CHANGED ? */
430 pim_upstream_update_join_desired (up
);
432 } /* PIM_RPF_CHANGED */
436 zlog_debug ("%s: NHT upstream %s old ifp %s new ifp %s",
437 __PRETTY_FUNCTION__
, up
->sg_str
,
438 old
.source_nexthop
.interface
->name
,
439 up
->rpf
.source_nexthop
.interface
->name
);
441 } /* for (pnc->upstream_list) */
443 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
446 struct pim_interface
*pim_ifp
= ifp
->info
;
447 struct pim_iface_upstream_switch
*us
;
449 for (ALL_LIST_ELEMENTS_RO (pim_ifp
->upstream_switch_list
, node
, us
))
452 rpf
.source_nexthop
.interface
= ifp
;
453 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
454 pim_joinprune_send (&rpf
, us
->us
);
455 pim_jp_agg_clear_group (us
->us
);
463 pim_compute_ecmp_hash (struct prefix
* src
, struct prefix
* grp
)
466 uint32_t s
= 0, g
= 0;
475 s
= src
->u
.prefix4
.s_addr
;
478 g
= grp
->u
.prefix4
.s_addr
;
485 hash_val
= jhash_2words (g
, s
, 101);
486 if (PIM_DEBUG_PIM_TRACE_DETAIL
)
488 char buf
[PREFIX2STR_BUFFER
];
489 char bufg
[PREFIX2STR_BUFFER
];
490 prefix2str (src
, buf
, sizeof (buf
));
492 prefix2str (grp
, bufg
, sizeof (bufg
));
493 zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__
, buf
,
494 grp
? bufg
: "", hash_val
);
501 pim_ecmp_nexthop_search (struct pim_nexthop_cache
*pnc
,
502 struct pim_nexthop
*nexthop
, struct prefix
*src
,
503 struct prefix
*grp
, int neighbor_needed
)
505 struct pim_neighbor
*nbr
= NULL
;
506 struct nexthop
*nh_node
= NULL
;
507 ifindex_t first_ifindex
;
508 struct interface
*ifp
= NULL
;
509 uint32_t hash_val
= 0, mod_val
= 0;
510 uint8_t nh_iter
= 0, found
= 0;
512 if (!pnc
|| !pnc
->nexthop_num
|| !nexthop
)
515 //Current Nexthop is VALID, check to stay on the current path.
516 if (nexthop
->interface
&& nexthop
->interface
->info
&&
517 nexthop
->mrib_nexthop_addr
.u
.prefix4
.s_addr
!=
520 /* User configured knob to explicitly switch
521 to new path is disabled or current path
522 metric is less than nexthop update.
525 if (qpim_ecmp_rebalance_enable
== 0)
527 uint8_t curr_route_valid
= 0;
528 //Check if current nexthop is present in new updated Nexthop list.
529 //If the current nexthop is not valid, candidate to choose new Nexthop.
530 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
)
531 curr_route_valid
= (nexthop
->interface
->ifindex
== nh_node
->ifindex
);
533 if (curr_route_valid
&&
534 !pim_if_connected_to_source (nexthop
->interface
,
537 nbr
= pim_neighbor_find (nexthop
->interface
,
538 nexthop
->mrib_nexthop_addr
.u
.prefix4
);
539 if (!nbr
&& !if_is_loopback (nexthop
->interface
))
542 zlog_debug ("%s: current nexthop does not have nbr ",
543 __PRETTY_FUNCTION__
);
549 char src_str
[INET_ADDRSTRLEN
];
550 pim_inet4_dump ("<addr?>", src
->u
.prefix4
, src_str
,
552 char grp_str
[INET_ADDRSTRLEN
];
553 pim_inet4_dump ("<addr?>", grp
->u
.prefix4
, grp_str
,
555 zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection",
556 __PRETTY_FUNCTION__
, src_str
, grp_str
,
557 nexthop
->interface
->name
);
564 if (qpim_ecmp_enable
)
566 //PIM ECMP flag is enable then choose ECMP path.
567 hash_val
= pim_compute_ecmp_hash (src
, grp
);
568 mod_val
= hash_val
% pnc
->nexthop_num
;
570 zlog_debug ("%s: hash_val %u mod_val %u ",
571 __PRETTY_FUNCTION__
, hash_val
, mod_val
);
574 for (nh_node
= pnc
->nexthop
; nh_node
&& (found
== 0);
575 nh_node
= nh_node
->next
)
577 first_ifindex
= nh_node
->ifindex
;
578 ifp
= if_lookup_by_index(first_ifindex
, VRF_DEFAULT
);
583 char addr_str
[INET_ADDRSTRLEN
];
584 pim_inet4_dump ("<addr?>", src
->u
.prefix4
, addr_str
,
586 zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)",
587 __FILE__
, __PRETTY_FUNCTION__
, first_ifindex
, addr_str
);
589 if (nh_iter
== mod_val
)
590 mod_val
++; //Select nexthpath
598 char addr_str
[INET_ADDRSTRLEN
];
599 pim_inet4_dump ("<addr?>", src
->u
.prefix4
, addr_str
,
601 zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
602 __PRETTY_FUNCTION__
, ifp
->name
, first_ifindex
, addr_str
);
604 if (nh_iter
== mod_val
)
605 mod_val
++; //Select nexthpath
611 && !pim_if_connected_to_source (ifp
, src
->u
.prefix4
))
613 nbr
= pim_neighbor_find (ifp
, nh_node
->gate
.ipv4
);
614 if (PIM_DEBUG_PIM_TRACE_DETAIL
)
615 zlog_debug ("ifp name: %s, pim nbr: %p", ifp
->name
, nbr
);
616 if (!nbr
&& !if_is_loopback (ifp
))
619 zlog_debug ("%s: pim nbr not found on input interface %s",
620 __PRETTY_FUNCTION__
, ifp
->name
);
621 if (nh_iter
== mod_val
)
622 mod_val
++; //Select nexthpath
628 if (nh_iter
== mod_val
)
630 nexthop
->interface
= ifp
;
631 nexthop
->mrib_nexthop_addr
.family
= AF_INET
;
632 nexthop
->mrib_nexthop_addr
.prefixlen
= IPV4_MAX_BITLEN
;
633 nexthop
->mrib_nexthop_addr
.u
.prefix4
= nh_node
->gate
.ipv4
;
634 nexthop
->mrib_metric_preference
= pnc
->distance
;
635 nexthop
->mrib_route_metric
= pnc
->metric
;
636 nexthop
->last_lookup
= src
->u
.prefix4
;
637 nexthop
->last_lookup_time
= pim_time_monotonic_usec ();
642 char buf
[INET_ADDRSTRLEN
];
643 char buf2
[INET_ADDRSTRLEN
];
644 char buf3
[INET_ADDRSTRLEN
];
645 pim_inet4_dump ("<src?>", src
->u
.prefix4
, buf2
, sizeof (buf2
));
646 pim_inet4_dump ("<grp?>", grp
->u
.prefix4
, buf3
, sizeof (buf3
));
647 pim_inet4_dump ("<rpf?>",
648 nexthop
->mrib_nexthop_addr
.u
.prefix4
, buf
,
650 zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d",
651 __PRETTY_FUNCTION__
, buf2
, buf3
, ifp
->name
,
652 buf
, mod_val
, nh_iter
, qpim_ecmp_enable
);
664 /* This API is used to parse Registered address nexthop update coming from Zebra */
666 pim_parse_nexthop_update (int command
, struct zclient
*zclient
,
667 zebra_size_t length
, vrf_id_t vrf_id
)
671 struct nexthop
*nexthop
;
672 struct nexthop
*nhlist_head
= NULL
;
673 struct nexthop
*nhlist_tail
= NULL
;
674 uint32_t metric
, distance
;
675 u_char nexthop_num
= 0;
678 struct pim_nexthop_cache
*pnc
= NULL
;
679 struct pim_neighbor
*nbr
= NULL
;
680 struct interface
*ifp
= NULL
;
683 memset (&p
, 0, sizeof (struct prefix
));
684 p
.family
= stream_getw (s
);
685 p
.prefixlen
= stream_getc (s
);
689 p
.u
.prefix4
.s_addr
= stream_get_ipv4 (s
);
692 stream_get (&p
.u
.prefix6
, s
, 16);
698 if (command
== ZEBRA_NEXTHOP_UPDATE
)
700 rpf
.rpf_addr
.family
= p
.family
;
701 rpf
.rpf_addr
.prefixlen
= p
.prefixlen
;
702 rpf
.rpf_addr
.u
.prefix4
.s_addr
= p
.u
.prefix4
.s_addr
;
703 pnc
= pim_nexthop_cache_find (&rpf
);
708 char buf
[PREFIX2STR_BUFFER
];
709 prefix2str (&rpf
.rpf_addr
, buf
, sizeof (buf
));
710 zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.",
711 __PRETTY_FUNCTION__
, buf
);
719 * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE
724 pnc
->last_update
= pim_time_monotonic_usec ();
725 distance
= stream_getc (s
);
726 metric
= stream_getl (s
);
727 nexthop_num
= stream_getc (s
);
731 pnc
->nexthop_num
= 0; //Only increment for pim enabled rpf.
733 for (i
= 0; i
< nexthop_num
; i
++)
735 nexthop
= nexthop_new ();
736 nexthop
->type
= stream_getc (s
);
737 switch (nexthop
->type
)
739 case NEXTHOP_TYPE_IPV4
:
740 nexthop
->gate
.ipv4
.s_addr
= stream_get_ipv4 (s
);
741 nexthop
->ifindex
= stream_getl (s
);
743 case NEXTHOP_TYPE_IFINDEX
:
744 nexthop
->ifindex
= stream_getl (s
);
746 case NEXTHOP_TYPE_IPV4_IFINDEX
:
747 nexthop
->gate
.ipv4
.s_addr
= stream_get_ipv4 (s
);
748 nexthop
->ifindex
= stream_getl (s
);
750 case NEXTHOP_TYPE_IPV6
:
751 stream_get (&nexthop
->gate
.ipv6
, s
, 16);
753 case NEXTHOP_TYPE_IPV6_IFINDEX
:
754 stream_get (&nexthop
->gate
.ipv6
, s
, 16);
755 nexthop
->ifindex
= stream_getl (s
);
756 struct interface
*ifp1
= if_lookup_by_index (nexthop
->ifindex
, VRF_DEFAULT
);
757 nbr
= pim_neighbor_find_if (ifp1
);
758 /* Overwrite with Nbr address as NH addr */
761 nexthop
->gate
.ipv4
= nbr
->source_addr
;
764 char str
[INET_ADDRSTRLEN
];
765 pim_inet4_dump ("<nht_nbr?>", nbr
->source_addr
, str
,
767 zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf",
768 __PRETTY_FUNCTION__
, str
, ifp1
->name
);
775 struct pim_interface
*pim_ifp
= ifp1
->info
;
776 zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ",
777 __PRETTY_FUNCTION__
, ifp1
->name
,
778 pim_ifp
->pim_neighbor_list
->count
);
780 //Mark nexthop address to 0 until PIM Nbr is resolved.
781 nexthop
->gate
.ipv4
.s_addr
= PIM_NET_INADDR_ANY
;
792 char p_str
[PREFIX2STR_BUFFER
];
793 prefix2str (&p
, p_str
, sizeof (p_str
));
794 zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ",
795 __PRETTY_FUNCTION__
, p_str
, i
+ 1,
796 inet_ntoa (nexthop
->gate
.ipv4
), nexthop
->type
, distance
,
800 ifp
= if_lookup_by_index (nexthop
->ifindex
, VRF_DEFAULT
);
805 char buf
[NEXTHOP_STRLEN
];
806 zlog_debug ("%s: could not find interface for ifindex %d (addr %s)",
807 __PRETTY_FUNCTION__
, nexthop
->ifindex
,
808 nexthop2str (nexthop
, buf
, sizeof (buf
)));
810 nexthop_free (nexthop
);
818 char buf
[NEXTHOP_STRLEN
];
819 zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)",
820 __PRETTY_FUNCTION__
, ifp
->name
, nexthop
->ifindex
,
821 nexthop2str (nexthop
, buf
, sizeof (buf
)));
823 nexthop_free (nexthop
);
829 nhlist_tail
->next
= nexthop
;
830 nhlist_tail
= nexthop
;
834 nhlist_tail
= nexthop
;
835 nhlist_head
= nexthop
;
837 //Only keep track of nexthops which are PIM enabled.
840 /* Reset existing pnc->nexthop before assigning new list */
841 nexthops_free (pnc
->nexthop
);
842 pnc
->nexthop
= nhlist_head
;
843 if (pnc
->nexthop_num
)
845 pnc
->flags
|= PIM_NEXTHOP_VALID
;
846 pnc
->distance
= distance
;
847 pnc
->metric
= metric
;
852 pnc
->flags
&= ~PIM_NEXTHOP_VALID
;
853 pnc
->nexthop_num
= nexthop_num
;
854 nexthops_free (pnc
->nexthop
);
860 char buf
[PREFIX2STR_BUFFER
];
861 prefix2str (&p
, buf
, sizeof (buf
));
862 zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d",
863 __PRETTY_FUNCTION__
, buf
, nexthop_num
, pnc
->nexthop_num
, vrf_id
,
864 listcount (pnc
->upstream_list
), listcount (pnc
->rp_list
));
867 pim_rpf_set_refresh_time ();
869 if (listcount (pnc
->rp_list
))
870 pim_update_rp_nh (pnc
);
871 if (listcount (pnc
->upstream_list
))
872 pim_update_upstream_nh (pnc
);
878 pim_ecmp_nexthop_lookup (struct pim_nexthop
*nexthop
, struct in_addr addr
,
879 struct prefix
*src
, struct prefix
*grp
,
882 struct pim_zlookup_nexthop nexthop_tab
[MULTIPATH_NUM
];
883 struct pim_neighbor
*nbr
= NULL
;
885 struct interface
*ifp
;
889 uint32_t hash_val
= 0, mod_val
= 0;
893 char addr_str
[INET_ADDRSTRLEN
];
894 pim_inet4_dump ("<addr?>", addr
, addr_str
, sizeof (addr_str
));
895 zlog_debug ("%s: Looking up: %s, last lookup time: %lld",
896 __PRETTY_FUNCTION__
, addr_str
, nexthop
->last_lookup_time
);
899 memset (nexthop_tab
, 0, sizeof (struct pim_zlookup_nexthop
) * MULTIPATH_NUM
);
900 num_ifindex
= zclient_lookup_nexthop (nexthop_tab
, MULTIPATH_NUM
, addr
,
901 PIM_NEXTHOP_LOOKUP_MAX
);
904 char addr_str
[INET_ADDRSTRLEN
];
905 pim_inet4_dump ("<addr?>", addr
, addr_str
, sizeof (addr_str
));
906 zlog_warn ("%s %s: could not find nexthop ifindex for address %s",
907 __FILE__
, __PRETTY_FUNCTION__
, addr_str
);
911 //If PIM ECMP enable then choose ECMP path.
912 if (qpim_ecmp_enable
)
914 hash_val
= pim_compute_ecmp_hash (src
, grp
);
915 mod_val
= hash_val
% num_ifindex
;
917 zlog_debug ("%s: hash_val %u mod_val %u",
918 __PRETTY_FUNCTION__
, hash_val
, mod_val
);
921 while (!found
&& (i
< num_ifindex
))
923 first_ifindex
= nexthop_tab
[i
].ifindex
;
925 ifp
= if_lookup_by_index (first_ifindex
, VRF_DEFAULT
);
930 char addr_str
[INET_ADDRSTRLEN
];
931 pim_inet4_dump ("<addr?>", addr
, addr_str
, sizeof (addr_str
));
932 zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)",
933 __FILE__
, __PRETTY_FUNCTION__
, first_ifindex
, addr_str
);
945 char addr_str
[INET_ADDRSTRLEN
];
946 pim_inet4_dump ("<addr?>", addr
, addr_str
, sizeof (addr_str
));
947 zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)",
948 __PRETTY_FUNCTION__
, ifp
->name
, first_ifindex
, addr_str
);
955 if (neighbor_needed
&& !pim_if_connected_to_source (ifp
, addr
))
957 nbr
= pim_neighbor_find (ifp
, nexthop_tab
[i
].nexthop_addr
.u
.prefix4
);
958 if (PIM_DEBUG_PIM_TRACE_DETAIL
)
959 zlog_debug ("ifp name: %s, pim nbr: %p", ifp
->name
, nbr
);
960 if (!nbr
&& !if_is_loopback (ifp
))
967 char addr_str
[INET_ADDRSTRLEN
];
968 pim_inet4_dump ("<addr?>", addr
, addr_str
,
970 zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)",
971 __PRETTY_FUNCTION__
, ifp
->name
, addr_str
);
981 char nexthop_str
[PREFIX_STRLEN
];
982 char addr_str
[INET_ADDRSTRLEN
];
983 pim_addr_dump ("<nexthop?>", &nexthop_tab
[i
].nexthop_addr
,
984 nexthop_str
, sizeof (nexthop_str
));
985 pim_inet4_dump ("<addr?>", addr
, addr_str
, sizeof (addr_str
));
986 zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d",
987 __FILE__
, __PRETTY_FUNCTION__
, nexthop_str
, addr_str
,
988 ifp
->name
, nexthop_tab
[i
].route_metric
,
989 nexthop_tab
[i
].protocol_distance
);
991 /* update nextop data */
992 nexthop
->interface
= ifp
;
993 nexthop
->mrib_nexthop_addr
= nexthop_tab
[i
].nexthop_addr
;
994 nexthop
->mrib_metric_preference
= nexthop_tab
[i
].protocol_distance
;
995 nexthop
->mrib_route_metric
= nexthop_tab
[i
].route_metric
;
996 nexthop
->last_lookup
= addr
;
997 nexthop
->last_lookup_time
= pim_time_monotonic_usec();
1009 int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr
,
1010 struct prefix
*src
, struct prefix
*grp
)
1012 struct pim_zlookup_nexthop nexthop_tab
[MULTIPATH_NUM
];
1015 ifindex_t first_ifindex
;
1016 uint32_t hash_val
= 0, mod_val
= 0;
1018 memset (nexthop_tab
, 0, sizeof (struct pim_zlookup_nexthop
) * MULTIPATH_NUM
);
1019 num_ifindex
= zclient_lookup_nexthop(nexthop_tab
, MULTIPATH_NUM
, addr
,
1020 PIM_NEXTHOP_LOOKUP_MAX
);
1021 if (num_ifindex
< 1)
1023 if (PIM_DEBUG_ZEBRA
)
1025 char addr_str
[INET_ADDRSTRLEN
];
1026 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1027 zlog_debug("%s %s: could not find nexthop ifindex for address %s",
1028 __FILE__
, __PRETTY_FUNCTION__
,
1034 //If PIM ECMP enable then choose ECMP path.
1035 if (qpim_ecmp_enable
)
1037 hash_val
= pim_compute_ecmp_hash (src
, grp
);
1038 mod_val
= hash_val
% num_ifindex
;
1039 if (PIM_DEBUG_TRACE
)
1040 zlog_debug ("%s: hash_val %u mod_val %u",
1041 __PRETTY_FUNCTION__
, hash_val
, mod_val
);
1044 first_ifindex
= nexthop_tab
[mod_val
].ifindex
;
1046 if (PIM_DEBUG_ZEBRA
)
1048 char addr_str
[INET_ADDRSTRLEN
];
1049 pim_inet4_dump("<ifaddr?>", addr
, addr_str
, sizeof(addr_str
));
1050 zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
1051 __FILE__
, __PRETTY_FUNCTION__
,
1052 first_ifindex
, ifindex2ifname(first_ifindex
, VRF_DEFAULT
), addr_str
);
1055 vif_index
= pim_if_find_vifindex_by_ifindex(first_ifindex
);
1059 if (PIM_DEBUG_ZEBRA
)
1061 char addr_str
[INET_ADDRSTRLEN
];
1062 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1063 zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s",
1064 __FILE__
, __PRETTY_FUNCTION__
,
1065 vif_index
, addr_str
);