1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* PIM for Quagga
* Copyright (C) 2017 Cumulus Networks, Inc.
* Chirag Shah
*/
#ifndef PIM_NHT_H
#define PIM_NHT_H
#include "prefix.h"
#include <zebra.h>
#include "zclient.h"
#include "vrf.h"
#include "pimd.h"
#include "pim_rp.h"
#include "pim_rpf.h"
PREDECL_SORTLIST_NONUNIQ(pim_lookup_mode);
struct pim_lookup_mode {
char *grp_plist;
char *src_plist;
enum pim_rpf_lookup_mode mode;
struct pim_lookup_mode_item list;
};
/* PIM nexthop cache value structure. */
struct pim_nexthop_cache_rib {
/* IGP route's metric. */
uint32_t metric;
uint32_t distance;
uint16_t prefix_len;
/* Nexthop number and nexthop linked list. */
uint16_t nexthop_num;
struct nexthop *nexthop;
int64_t last_update;
uint16_t flags;
#define PIM_NEXTHOP_VALID (1 << 0)
#define PIM_NEXTHOP_ANSWER_RECEIVED (1 << 1)
};
struct pim_nexthop_cache {
pim_addr addr;
struct pim_nexthop_cache_rib mrib;
struct pim_nexthop_cache_rib urib;
struct list *rp_list;
struct hash *upstream_hash;
/* bsr_count won't currently go above 1 as we only have global_scope,
* but if anyone adds scope support multiple scopes may NHT-track the
* same BSR
*/
uint32_t bsr_count;
uint32_t candrp_count;
};
struct pnc_hash_walk_data {
struct pim_instance *pim;
struct interface *ifp;
};
/* Find the right lookup mode for the given group and/or source
* either may be ANY (although source should realistically always be provided)
* Find the lookup mode that has matching group and/or source prefix lists, or the global mode.
*/
enum pim_rpf_lookup_mode pim_get_lookup_mode(struct pim_instance *pim, pim_addr group,
pim_addr source);
/* Change the RPF lookup config, may trigger updates to RP's and Upstreams registered for matching cache entries */
void pim_nht_change_rpf_mode(struct pim_instance *pim, const char *group_plist,
const char *source_plist, enum pim_rpf_lookup_mode mode);
/* Write the rpf lookup mode configuration */
int pim_lookup_mode_write(struct pim_instance *pim, struct vty *vty);
/* Verify that we have nexthop information in the cache entry */
bool pim_nht_pnc_is_valid(struct pim_instance *pim, struct pim_nexthop_cache *pnc, pim_addr group);
/* Get (or add) the NH cache entry for the given address */
struct pim_nexthop_cache *pim_nht_get(struct pim_instance *pim, pim_addr addr);
/* Set the gateway address for all nexthops in the given cache entry to the given address
* unless the gateway is already set, and only if the nexthop is through the given interface.
*/
void pim_nht_set_gateway(struct pim_instance *pim, struct pim_nexthop_cache *pnc, pim_addr addr,
struct interface *ifp);
/* Track a new addr, registers an upstream or RP for updates */
bool pim_nht_find_or_track(struct pim_instance *pim, pim_addr addr, struct pim_upstream *up,
struct rp_info *rp, struct pim_nexthop_cache *out_pnc);
/* Track a new addr, increments BSR count */
void pim_nht_bsr_add(struct pim_instance *pim, pim_addr bsr_addr);
/* Track a new addr, increments Cand RP count */
bool pim_nht_candrp_add(struct pim_instance *pim, pim_addr addr);
/* Delete a tracked addr with registered upstream or RP, if no-one else is interested, stop tracking */
void pim_nht_delete_tracked(struct pim_instance *pim, pim_addr addr, struct pim_upstream *up,
struct rp_info *rp);
/* Delete a tracked addr and decrement BSR count, if no-one else is interested, stop tracking */
void pim_nht_bsr_del(struct pim_instance *pim, pim_addr bsr_addr);
/* Delete a tracked addr and decrement Cand RP count, if no-one else is interested, stop tracking */
void pim_nht_candrp_del(struct pim_instance *pim, pim_addr addr);
/* RPF(bsr_addr) == src_ip%src_ifp? */
bool pim_nht_bsr_rpf_check(struct pim_instance *pim, pim_addr bsr_addr, struct interface *src_ifp,
pim_addr src_ip);
/* Reset the rp.source_nexthop of the given RP */
void pim_nht_rp_del(struct rp_info *rp_info);
/* Walk the NH cache and update every nexthop that uses the given interface */
void pim_nht_upstream_if_update(struct pim_instance *pim, struct interface *ifp);
/* Lookup nexthop information for src, returned in nexthop when function returns true.
* Tries to find in cache first and does a synchronous lookup if not found in the cache.
* If neighbor_needed is true, then nexthop is only considered valid if it's to a pim
* neighbor.
* Providing the group only effects the ECMP decision, if enabled
*/
bool pim_nht_lookup_ecmp(struct pim_instance *pim, struct pim_nexthop *nexthop, pim_addr src,
struct prefix *grp, bool neighbor_needed);
/* Very similar to pim_nht_lookup_ecmp, but does not check the nht cache and only does
* a synchronous lookup. No ECMP decision is made.
*/
bool pim_nht_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, pim_addr addr,
pim_addr group, bool neighbor_needed);
/* Performs a pim_nht_lookup_ecmp and returns the mroute VIF index of the nexthop interface */
int pim_nht_lookup_ecmp_if_vif_index(struct pim_instance *pim, pim_addr src, struct prefix *grp);
/* Tracked nexthop update from zebra */
void pim_nexthop_update(struct vrf *vrf, struct prefix *match, struct zapi_route *nhr);
/* NHT init and finish funcitons */
void pim_nht_init(struct pim_instance *pim);
void pim_nht_terminate(struct pim_instance *pim);
#endif
|