3 * Copyright (C) 2018 Cumulus Networks, Inc.
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRR 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
24 #include <nexthop_group.h>
31 #include "pbrd/pbr_nht.h"
32 #include "pbrd/pbr_map.h"
33 #include "pbrd/pbr_zebra.h"
34 #include "pbrd/pbr_memory.h"
35 #include "pbrd/pbr_debug.h"
37 DEFINE_MTYPE_STATIC(PBRD
, PBR_NHG
, "PBR Nexthop Groups")
39 static struct hash
*pbr_nhg_hash
;
40 static struct hash
*pbr_nhrc_hash
;
42 static uint32_t pbr_nhg_low_table
;
43 static uint32_t pbr_nhg_high_table
;
44 static uint32_t pbr_nhg_low_rule
;
45 static uint32_t pbr_nhg_high_rule
;
46 static bool nhg_tableid
[65535];
48 static void pbr_nht_install_nexthop_group(struct pbr_nexthop_group_cache
*pnhgc
,
49 struct nexthop_group nhg
);
51 pbr_nht_uninstall_nexthop_group(struct pbr_nexthop_group_cache
*pnhgc
,
52 struct nexthop_group nhg
,
53 enum nexthop_types_t nh_afi
);
59 struct nexthop nexthop
;
60 unsigned int refcount
;
63 /* Hash functions for pbr_nhrc_hash ---------------------------------------- */
65 static void *pbr_nhrc_hash_alloc(void *p
)
67 struct nhrc
*nhrc
= XCALLOC(MTYPE_PBR_NHG
, sizeof(struct nhrc
));
68 nhrc
->nexthop
= *(struct nexthop
*)p
;
72 static int pbr_nhrc_hash_equal(const void *arg1
, const void *arg2
)
74 const struct nexthop
*nh1
, *nh2
;
79 return nexthop_same(nh1
, nh2
);
82 /* ------------------------------------------------------------------------- */
84 static void *pbr_nh_alloc(void *p
)
86 struct pbr_nexthop_cache
*new;
87 struct pbr_nexthop_cache
*pnhc
= (struct pbr_nexthop_cache
*)p
;
90 new = XCALLOC(MTYPE_PBR_NHG
, sizeof(*new));
91 nhrc
= hash_get(pbr_nhrc_hash
, pnhc
->nexthop
, pbr_nhrc_hash_alloc
);
92 new->nexthop
= &nhrc
->nexthop
;
94 /* Decremented again in pbr_nh_delete */
97 DEBUGD(&pbr_dbg_nht
, "%s: Sending nexthop to Zebra",
100 pbr_send_rnh(new->nexthop
, true);
106 static void pbr_nh_delete(struct pbr_nexthop_cache
**pnhc
)
110 nhrc
= hash_lookup(pbr_nhrc_hash
, (*pnhc
)->nexthop
);
114 if (!nhrc
|| nhrc
->refcount
== 0) {
115 DEBUGD(&pbr_dbg_nht
, "%s: Removing nexthop from Zebra",
116 __PRETTY_FUNCTION__
);
117 pbr_send_rnh((*pnhc
)->nexthop
, false);
119 if (nhrc
&& nhrc
->refcount
== 0) {
120 hash_release(pbr_nhrc_hash
, nhrc
);
121 XFREE(MTYPE_PBR_NHG
, nhrc
);
124 XFREE(MTYPE_PBR_NHG
, *pnhc
);
127 static void pbr_nh_delete_iterate(struct hash_backet
*b
, void *p
)
129 pbr_nh_delete((struct pbr_nexthop_cache
**)&b
->data
);
132 static uint32_t pbr_nh_hash_key(void *arg
)
135 struct pbr_nexthop_cache
*pbrnc
= (struct pbr_nexthop_cache
*)arg
;
137 key
= nexthop_hash(pbrnc
->nexthop
);
142 static int pbr_nh_hash_equal(const void *arg1
, const void *arg2
)
144 const struct pbr_nexthop_cache
*pbrnc1
=
145 (const struct pbr_nexthop_cache
*)arg1
;
146 const struct pbr_nexthop_cache
*pbrnc2
=
147 (const struct pbr_nexthop_cache
*)arg2
;
149 if (pbrnc1
->nexthop
->vrf_id
!= pbrnc2
->nexthop
->vrf_id
)
152 if (pbrnc1
->nexthop
->ifindex
!= pbrnc2
->nexthop
->ifindex
)
155 if (pbrnc1
->nexthop
->type
!= pbrnc2
->nexthop
->type
)
158 switch (pbrnc1
->nexthop
->type
) {
159 case NEXTHOP_TYPE_IFINDEX
:
161 case NEXTHOP_TYPE_IPV4_IFINDEX
:
162 case NEXTHOP_TYPE_IPV4
:
163 return pbrnc1
->nexthop
->gate
.ipv4
.s_addr
164 == pbrnc2
->nexthop
->gate
.ipv4
.s_addr
;
165 case NEXTHOP_TYPE_IPV6_IFINDEX
:
166 case NEXTHOP_TYPE_IPV6
:
167 return !memcmp(&pbrnc1
->nexthop
->gate
.ipv6
,
168 &pbrnc2
->nexthop
->gate
.ipv6
, 16);
169 case NEXTHOP_TYPE_BLACKHOLE
:
170 return pbrnc1
->nexthop
->bh_type
== pbrnc2
->nexthop
->bh_type
;
174 * We should not get here
179 static void pbr_nhgc_delete(struct pbr_nexthop_group_cache
*p
)
181 hash_iterate(p
->nhh
, pbr_nh_delete_iterate
, NULL
);
183 XFREE(MTYPE_PBR_NHG
, p
);
186 static void *pbr_nhgc_alloc(void *p
)
188 struct pbr_nexthop_group_cache
*new;
189 struct pbr_nexthop_group_cache
*pnhgc
=
190 (struct pbr_nexthop_group_cache
*)p
;
192 new = XCALLOC(MTYPE_PBR_NHG
, sizeof(*new));
194 strcpy(new->name
, pnhgc
->name
);
195 new->table_id
= pbr_nht_get_next_tableid(false);
197 DEBUGD(&pbr_dbg_nht
, "%s: NHT: %s assigned Table ID: %u",
198 __PRETTY_FUNCTION__
, new->name
, new->table_id
);
200 new->nhh
= hash_create_size(8, pbr_nh_hash_key
, pbr_nh_hash_equal
,
201 "PBR NH Cache Hash");
206 void pbr_nhgroup_add_cb(const char *name
)
208 struct pbr_nexthop_group_cache
*pnhgc
;
209 struct nexthop_group_cmd
*nhgc
;
211 nhgc
= nhgc_find(name
);
214 DEBUGD(&pbr_dbg_nht
, "%s: Could not find nhgc with name: %s\n",
215 __PRETTY_FUNCTION__
, name
);
219 pnhgc
= pbr_nht_add_group(name
);
224 DEBUGD(&pbr_dbg_nht
, "%s: Added nexthop-group %s", __PRETTY_FUNCTION__
,
227 pbr_nht_install_nexthop_group(pnhgc
, nhgc
->nhg
);
228 pbr_map_check_nh_group_change(name
);
231 void pbr_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd
*nhgc
,
232 const struct nexthop
*nhop
)
235 struct pbr_nexthop_group_cache pnhgc_find
= {};
236 struct pbr_nexthop_group_cache
*pnhgc
;
237 struct pbr_nexthop_cache pnhc_find
= {};
238 struct pbr_nexthop_cache
*pnhc
;
240 if (!pbr_nht_get_next_tableid(true)) {
242 "%s: Exhausted all table identifiers; cannot create nexthop-group cache for nexthop-group '%s'",
243 __PRETTY_FUNCTION__
, nhgc
->name
);
247 /* find pnhgc by name */
248 strlcpy(pnhgc_find
.name
, nhgc
->name
, sizeof(pnhgc_find
.name
));
249 pnhgc
= hash_get(pbr_nhg_hash
, &pnhgc_find
, pbr_nhgc_alloc
);
251 /* create & insert new pnhc into pnhgc->nhh */
252 pnhc_find
.nexthop
= (struct nexthop
*)nhop
;
253 pnhc
= hash_get(pnhgc
->nhh
, &pnhc_find
, pbr_nh_alloc
);
254 pnhc_find
.nexthop
= NULL
;
256 /* set parent pnhgc */
257 pnhc
->parent
= pnhgc
;
259 if (DEBUG_MODE_CHECK(&pbr_dbg_nht
, DEBUG_MODE_ALL
)) {
260 nexthop2str(nhop
, debugstr
, sizeof(debugstr
));
261 DEBUGD(&pbr_dbg_nht
, "%s: Added %s to nexthop-group %s",
262 __PRETTY_FUNCTION__
, debugstr
, nhgc
->name
);
265 pbr_nht_install_nexthop_group(pnhgc
, nhgc
->nhg
);
266 pbr_map_check_nh_group_change(nhgc
->name
);
269 void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd
*nhgc
,
270 const struct nexthop
*nhop
)
273 struct pbr_nexthop_group_cache pnhgc_find
= {};
274 struct pbr_nexthop_group_cache
*pnhgc
;
275 struct pbr_nexthop_cache pnhc_find
= {};
276 struct pbr_nexthop_cache
*pnhc
;
277 enum nexthop_types_t nh_afi
= nhop
->type
;
279 /* find pnhgc by name */
280 strlcpy(pnhgc_find
.name
, nhgc
->name
, sizeof(pnhgc_find
.name
));
281 pnhgc
= hash_lookup(pbr_nhg_hash
, &pnhgc_find
);
283 /* delete pnhc from pnhgc->nhh */
284 pnhc_find
.nexthop
= (struct nexthop
*)nhop
;
285 pnhc
= hash_release(pnhgc
->nhh
, &pnhc_find
);
288 pbr_nh_delete(&pnhc
);
290 if (DEBUG_MODE_CHECK(&pbr_dbg_nht
, DEBUG_MODE_ALL
)) {
291 nexthop2str(nhop
, debugstr
, sizeof(debugstr
));
292 DEBUGD(&pbr_dbg_nht
, "%s: Removed %s from nexthop-group %s",
293 __PRETTY_FUNCTION__
, debugstr
, nhgc
->name
);
296 if (pnhgc
->nhh
->count
)
297 pbr_nht_install_nexthop_group(pnhgc
, nhgc
->nhg
);
299 pbr_nht_uninstall_nexthop_group(pnhgc
, nhgc
->nhg
, nh_afi
);
301 pbr_map_check_nh_group_change(nhgc
->name
);
304 void pbr_nhgroup_delete_cb(const char *name
)
306 DEBUGD(&pbr_dbg_nht
, "%s: Removed nexthop-group %s",
307 __PRETTY_FUNCTION__
, name
);
309 /* delete group from all pbrms's */
310 pbr_nht_delete_group(name
);
312 pbr_map_check_nh_group_change(name
);
316 static struct pbr_nexthop_cache
*pbr_nht_lookup_nexthop(struct nexthop
*nexthop
)
322 static void pbr_nht_find_nhg_from_table_install(struct hash_backet
*b
,
325 struct pbr_nexthop_group_cache
*pnhgc
=
326 (struct pbr_nexthop_group_cache
*)b
->data
;
327 uint32_t *table_id
= (uint32_t *)data
;
329 if (pnhgc
->table_id
== *table_id
) {
330 DEBUGD(&pbr_dbg_nht
, "%s: Table ID (%u) matches %s",
331 __PRETTY_FUNCTION__
, *table_id
, pnhgc
->name
);
334 * If the table has been re-handled by zebra
335 * and we are already installed no need to do
338 if (!pnhgc
->installed
) {
339 pnhgc
->installed
= true;
340 pbr_map_schedule_policy_from_nhg(pnhgc
->name
);
345 void pbr_nht_route_installed_for_table(uint32_t table_id
)
347 hash_iterate(pbr_nhg_hash
, pbr_nht_find_nhg_from_table_install
,
351 static void pbr_nht_find_nhg_from_table_remove(struct hash_backet
*b
,
357 void pbr_nht_route_removed_for_table(uint32_t table_id
)
359 hash_iterate(pbr_nhg_hash
, pbr_nht_find_nhg_from_table_remove
,
364 * Loop through all nexthops in a nexthop group to check that they are all the
365 * same. If they are not all the same, log this peculiarity.
368 * The nexthop group to check
371 * - AFI of last nexthop in the group
374 static afi_t
pbr_nht_which_afi(struct nexthop_group nhg
,
375 enum nexthop_types_t nh_afi
)
377 struct nexthop
*nexthop
;
378 afi_t install_afi
= AFI_MAX
;
381 v6
= v4
= bh
= false;
384 for (ALL_NEXTHOPS(nhg
, nexthop
)) {
385 nh_afi
= nexthop
->type
;
391 case NEXTHOP_TYPE_IFINDEX
:
393 case NEXTHOP_TYPE_IPV4
:
394 case NEXTHOP_TYPE_IPV4_IFINDEX
:
396 install_afi
= AFI_IP
;
398 case NEXTHOP_TYPE_IPV6
:
399 case NEXTHOP_TYPE_IPV6_IFINDEX
:
401 install_afi
= AFI_IP6
;
403 case NEXTHOP_TYPE_BLACKHOLE
:
405 install_afi
= AFI_MAX
;
411 "%s: Saw both V6 and V4 nexthops...using %s",
412 __PRETTY_FUNCTION__
, afi2str(install_afi
));
413 if (bh
&& (v6
|| v4
))
415 "%s: Saw blackhole nexthop(s) with %s%s%s nexthop(s), using AFI_MAX.",
416 __PRETTY_FUNCTION__
, v4
? "v4" : "",
417 (v4
&& v6
) ? " and " : "", v6
? "v6" : "");
422 static void pbr_nht_install_nexthop_group(struct pbr_nexthop_group_cache
*pnhgc
,
423 struct nexthop_group nhg
)
426 enum nexthop_types_t nh_afi
= 0;
428 install_afi
= pbr_nht_which_afi(nhg
, nh_afi
);
430 route_add(pnhgc
, nhg
, install_afi
);
434 pbr_nht_uninstall_nexthop_group(struct pbr_nexthop_group_cache
*pnhgc
,
435 struct nexthop_group nhg
,
436 enum nexthop_types_t nh_afi
)
440 install_afi
= pbr_nht_which_afi(nhg
, nh_afi
);
442 pnhgc
->installed
= false;
443 pnhgc
->valid
= false;
444 route_delete(pnhgc
, install_afi
);
447 void pbr_nht_change_group(const char *name
)
449 struct nexthop_group_cmd
*nhgc
;
450 struct pbr_nexthop_group_cache
*pnhgc
;
451 struct pbr_nexthop_group_cache find
;
452 struct nexthop
*nhop
;
454 nhgc
= nhgc_find(name
);
458 memset(&find
, 0, sizeof(find
));
459 snprintf(find
.name
, sizeof(find
.name
), "%s", name
);
460 pnhgc
= hash_lookup(pbr_nhg_hash
, &find
);
464 "%s: Could not find nexthop-group cache w/ name '%s'",
465 __PRETTY_FUNCTION__
, name
);
469 for (ALL_NEXTHOPS(nhgc
->nhg
, nhop
)) {
470 struct pbr_nexthop_cache lookup
;
471 struct pbr_nexthop_cache
*pnhc
;
473 lookup
.nexthop
= nhop
;
474 pnhc
= hash_lookup(pnhgc
->nhh
, &lookup
);
476 pnhc
= hash_get(pnhgc
->nhh
, &lookup
, pbr_nh_alloc
);
477 pnhc
->parent
= pnhgc
;
480 pbr_nht_install_nexthop_group(pnhgc
, nhgc
->nhg
);
483 char *pbr_nht_nexthop_make_name(char *name
, size_t l
,
484 uint32_t seqno
, char *buffer
)
486 snprintf(buffer
, l
, "%s%u", name
, seqno
);
490 void pbr_nht_add_individual_nexthop(struct pbr_map_sequence
*pbrms
)
492 struct pbr_nexthop_group_cache
*pnhgc
;
493 struct pbr_nexthop_group_cache find
;
494 struct pbr_nexthop_cache
*pnhc
;
495 struct pbr_nexthop_cache lookup
;
497 memset(&find
, 0, sizeof(find
));
498 pbr_nht_nexthop_make_name(pbrms
->parent
->name
, PBR_NHC_NAMELEN
,
499 pbrms
->seqno
, find
.name
);
501 if (!pbr_nht_get_next_tableid(true)) {
503 "%s: Exhausted all table identifiers; cannot create nexthop-group cache for nexthop-group '%s'",
504 __PRETTY_FUNCTION__
, find
.name
);
508 if (!pbrms
->internal_nhg_name
)
509 pbrms
->internal_nhg_name
= XSTRDUP(MTYPE_TMP
, find
.name
);
511 pnhgc
= hash_get(pbr_nhg_hash
, &find
, pbr_nhgc_alloc
);
513 lookup
.nexthop
= pbrms
->nhg
->nexthop
;
514 pnhc
= hash_get(pnhgc
->nhh
, &lookup
, pbr_nh_alloc
);
515 pnhc
->parent
= pnhgc
;
516 pbr_nht_install_nexthop_group(pnhgc
, *pbrms
->nhg
);
519 void pbr_nht_delete_individual_nexthop(struct pbr_map_sequence
*pbrms
)
521 struct pbr_nexthop_group_cache
*pnhgc
;
522 struct pbr_nexthop_group_cache find
;
523 struct pbr_nexthop_cache
*pnhc
;
524 struct pbr_nexthop_cache lup
;
525 struct pbr_map
*pbrm
= pbrms
->parent
;
526 struct listnode
*node
;
527 struct pbr_map_interface
*pmi
;
529 enum nexthop_types_t nh_afi
= 0;
531 if (pbrm
->valid
&& pbrms
->nhs_installed
&& pbrm
->incoming
->count
) {
532 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
))
533 pbr_send_pbr_map(pbrms
, pmi
, false);
537 pbrms
->nhs_installed
= false;
538 pbrms
->reason
|= PBR_MAP_INVALID_NO_NEXTHOPS
;
540 memset(&find
, 0, sizeof(find
));
541 snprintf(find
.name
, sizeof(find
.name
), "%s", pbrms
->internal_nhg_name
);
542 pnhgc
= hash_lookup(pbr_nhg_hash
, &find
);
544 nh
= pbrms
->nhg
->nexthop
;
547 pnhc
= hash_lookup(pnhgc
->nhh
, &lup
);
549 hash_release(pnhgc
->nhh
, pnhc
);
550 pbr_nh_delete(&pnhc
);
551 pbr_nht_uninstall_nexthop_group(pnhgc
, *pbrms
->nhg
, nh_afi
);
553 hash_release(pbr_nhg_hash
, pnhgc
);
555 nexthop_del(pbrms
->nhg
, nh
);
557 nexthop_group_delete(&pbrms
->nhg
);
558 XFREE(MTYPE_TMP
, pbrms
->internal_nhg_name
);
561 struct pbr_nexthop_group_cache
*pbr_nht_add_group(const char *name
)
563 struct nexthop
*nhop
;
564 struct nexthop_group_cmd
*nhgc
;
565 struct pbr_nexthop_group_cache
*pnhgc
;
566 struct pbr_nexthop_group_cache lookup
;
568 if (!pbr_nht_get_next_tableid(true)) {
570 "%s: Exhausted all table identifiers; cannot create nexthop-group cache for nexthop-group '%s'",
571 __PRETTY_FUNCTION__
, name
);
575 nhgc
= nhgc_find(name
);
578 DEBUGD(&pbr_dbg_nht
, "%s: Could not find nhgc with name: %s\n",
579 __PRETTY_FUNCTION__
, name
);
583 snprintf(lookup
.name
, sizeof(lookup
.name
), "%s", name
);
584 pnhgc
= hash_get(pbr_nhg_hash
, &lookup
, pbr_nhgc_alloc
);
585 DEBUGD(&pbr_dbg_nht
, "%s: Retrieved NHGC @ %p", __PRETTY_FUNCTION__
,
588 for (ALL_NEXTHOPS(nhgc
->nhg
, nhop
)) {
589 struct pbr_nexthop_cache lookupc
;
590 struct pbr_nexthop_cache
*pnhc
;
592 lookupc
.nexthop
= nhop
;
593 pnhc
= hash_lookup(pnhgc
->nhh
, &lookupc
);
595 pnhc
= hash_get(pnhgc
->nhh
, &lookupc
, pbr_nh_alloc
);
596 pnhc
->parent
= pnhgc
;
603 void pbr_nht_delete_group(const char *name
)
605 struct pbr_map_sequence
*pbrms
;
606 struct listnode
*snode
;
607 struct pbr_map
*pbrm
;
608 struct pbr_nexthop_group_cache pnhgc_find
;
609 struct pbr_nexthop_group_cache
*pnhgc
;
611 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
612 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, snode
, pbrms
)) {
613 if (pbrms
->nhgrp_name
614 && strmatch(pbrms
->nhgrp_name
, name
)) {
615 pbrms
->reason
|= PBR_MAP_INVALID_NO_NEXTHOPS
;
616 nexthop_group_delete(&pbrms
->nhg
);
618 pbrms
->internal_nhg_name
= NULL
;
624 strlcpy(pnhgc_find
.name
, name
, sizeof(pnhgc_find
.name
));
625 pnhgc
= hash_release(pbr_nhg_hash
, &pnhgc_find
);
626 pbr_nhgc_delete(pnhgc
);
629 bool pbr_nht_nexthop_valid(struct nexthop_group
*nhg
)
631 DEBUGD(&pbr_dbg_nht
, "%s: %p", __PRETTY_FUNCTION__
, nhg
);
635 bool pbr_nht_nexthop_group_valid(const char *name
)
637 struct pbr_nexthop_group_cache
*pnhgc
;
638 struct pbr_nexthop_group_cache lookup
;
640 DEBUGD(&pbr_dbg_nht
, "%s: %s", __PRETTY_FUNCTION__
, name
);
642 snprintf(lookup
.name
, sizeof(lookup
.name
), "%s", name
);
643 pnhgc
= hash_get(pbr_nhg_hash
, &lookup
, NULL
);
646 DEBUGD(&pbr_dbg_nht
, "%s: \t%d %d", __PRETTY_FUNCTION__
, pnhgc
->valid
,
648 if (pnhgc
->valid
&& pnhgc
->installed
)
654 struct pbr_nht_individual
{
655 struct zapi_route
*nhr
;
660 static void pbr_nht_individual_nexthop_update_lookup(struct hash_backet
*b
,
663 struct pbr_nexthop_cache
*pnhc
= b
->data
;
664 struct pbr_nht_individual
*pnhi
= data
;
665 char buf
[PREFIX_STRLEN
];
668 old_valid
= pnhc
->valid
;
670 switch (pnhi
->nhr
->prefix
.family
) {
672 if (pnhc
->nexthop
->gate
.ipv4
.s_addr
673 == pnhi
->nhr
->prefix
.u
.prefix4
.s_addr
)
674 pnhc
->valid
= !!pnhi
->nhr
->nexthop_num
;
677 if (memcmp(&pnhc
->nexthop
->gate
.ipv6
,
678 &pnhi
->nhr
->prefix
.u
.prefix6
, 16)
680 pnhc
->valid
= !!pnhi
->nhr
->nexthop_num
;
684 DEBUGD(&pbr_dbg_nht
, "\tFound %s: old: %d new: %d",
685 prefix2str(&pnhi
->nhr
->prefix
, buf
, sizeof(buf
)), old_valid
,
692 static void pbr_nht_nexthop_update_lookup(struct hash_backet
*b
, void *data
)
694 struct pbr_nexthop_group_cache
*pnhgc
= b
->data
;
695 struct pbr_nht_individual pnhi
;
698 old_valid
= pnhgc
->valid
;
700 pnhi
.nhr
= (struct zapi_route
*)data
;
702 hash_iterate(pnhgc
->nhh
, pbr_nht_individual_nexthop_update_lookup
,
706 * If any of the specified nexthops are valid we are valid
708 pnhgc
->valid
= !!pnhi
.valid
;
710 if (old_valid
!= pnhgc
->valid
)
711 pbr_map_check_nh_group_change(pnhgc
->name
);
714 void pbr_nht_nexthop_update(struct zapi_route
*nhr
)
716 hash_iterate(pbr_nhg_hash
, pbr_nht_nexthop_update_lookup
, nhr
);
719 static uint32_t pbr_nhg_hash_key(void *arg
)
721 struct pbr_nexthop_group_cache
*nhgc
=
722 (struct pbr_nexthop_group_cache
*)arg
;
724 return jhash(&nhgc
->name
, strlen(nhgc
->name
), 0x52c34a96);
727 static int pbr_nhg_hash_equal(const void *arg1
, const void *arg2
)
729 const struct pbr_nexthop_group_cache
*nhgc1
=
730 (const struct pbr_nexthop_group_cache
*)arg1
;
731 const struct pbr_nexthop_group_cache
*nhgc2
=
732 (const struct pbr_nexthop_group_cache
*)arg2
;
734 return !strcmp(nhgc1
->name
, nhgc2
->name
);
737 uint32_t pbr_nht_get_next_tableid(bool peek
)
742 for (i
= pbr_nhg_low_table
; i
<= pbr_nhg_high_table
; i
++) {
743 if (nhg_tableid
[i
] == false) {
750 nhg_tableid
[i
] = !peek
;
756 void pbr_nht_set_tableid_range(uint32_t low
, uint32_t high
)
758 pbr_nhg_low_table
= low
;
759 pbr_nhg_high_table
= high
;
762 void pbr_nht_write_table_range(struct vty
*vty
)
764 if (pbr_nhg_low_table
!= PBR_NHT_DEFAULT_LOW_TABLEID
765 || pbr_nhg_high_table
!= PBR_NHT_DEFAULT_HIGH_TABLEID
) {
766 vty_out(vty
, "pbr table range %u %u\n", pbr_nhg_low_table
,
771 uint32_t pbr_nht_get_next_rule(uint32_t seqno
)
773 return seqno
+ pbr_nhg_low_rule
- 1;
775 void pbr_nht_set_rule_range(uint32_t low
, uint32_t high
)
777 pbr_nhg_low_rule
= low
;
778 pbr_nhg_high_rule
= high
;
781 void pbr_nht_write_rule_range(struct vty
*vty
)
783 if (pbr_nhg_low_rule
!= PBR_NHT_DEFAULT_LOW_RULE
784 || pbr_nhg_high_rule
!= PBR_NHT_DEFAULT_HIGH_RULE
) {
785 vty_out(vty
, "pbr rule range %u %u\n", pbr_nhg_low_rule
,
790 uint32_t pbr_nht_get_table(const char *name
)
792 struct pbr_nexthop_group_cache find
;
793 struct pbr_nexthop_group_cache
*pnhgc
;
795 memset(&find
, 0, sizeof(find
));
796 snprintf(find
.name
, sizeof(find
.name
), "%s", name
);
797 pnhgc
= hash_lookup(pbr_nhg_hash
, &find
);
801 "%s: Could not find nexthop-group cache w/ name '%s'",
802 __PRETTY_FUNCTION__
, name
);
806 return pnhgc
->table_id
;
809 bool pbr_nht_get_installed(const char *name
)
811 struct pbr_nexthop_group_cache find
;
812 struct pbr_nexthop_group_cache
*pnhgc
;
814 memset(&find
, 0, sizeof(find
));
815 snprintf(find
.name
, sizeof(find
.name
), "%s", name
);
817 pnhgc
= hash_lookup(pbr_nhg_hash
, &find
);
822 return pnhgc
->installed
;
825 static void pbr_nht_show_nhg_nexthops(struct hash_backet
*b
, void *data
)
827 struct pbr_nexthop_cache
*pnhc
= b
->data
;
828 struct vty
*vty
= data
;
830 vty_out(vty
, "\tValid: %d ", pnhc
->valid
);
831 nexthop_group_write_nexthop(vty
, pnhc
->nexthop
);
834 struct pbr_nht_show
{
839 static void pbr_nht_show_nhg(struct hash_backet
*b
, void *data
)
841 struct pbr_nexthop_group_cache
*pnhgc
= b
->data
;
842 struct pbr_nht_show
*pns
= data
;
845 if (pns
->name
&& strcmp(pns
->name
, pnhgc
->name
) != 0)
849 vty_out(vty
, "Nexthop-Group: %s Table: %u Valid: %d Installed: %d\n",
850 pnhgc
->name
, pnhgc
->table_id
, pnhgc
->valid
, pnhgc
->installed
);
852 hash_iterate(pnhgc
->nhh
, pbr_nht_show_nhg_nexthops
, vty
);
855 void pbr_nht_show_nexthop_group(struct vty
*vty
, const char *name
)
857 struct pbr_nht_show pns
;
862 hash_iterate(pbr_nhg_hash
, pbr_nht_show_nhg
, &pns
);
865 void pbr_nht_init(void)
867 pbr_nhg_hash
= hash_create_size(
868 16, pbr_nhg_hash_key
, pbr_nhg_hash_equal
, "PBR NHG Cache Hash");
870 hash_create_size(16, (unsigned int (*)(void *))nexthop_hash
,
871 pbr_nhrc_hash_equal
, "PBR NH Hash");
873 pbr_nhg_low_table
= PBR_NHT_DEFAULT_LOW_TABLEID
;
874 pbr_nhg_high_table
= PBR_NHT_DEFAULT_HIGH_TABLEID
;
875 pbr_nhg_low_rule
= PBR_NHT_DEFAULT_LOW_RULE
;
876 pbr_nhg_high_rule
= PBR_NHT_DEFAULT_HIGH_RULE
;
877 memset(&nhg_tableid
, 0, 65535 * sizeof(uint8_t));