]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_nht.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / staticd / static_nht.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Static NHT code.
4 * Copyright (C) 2018 Cumulus Networks, Inc.
5 * Donald Sharp
6 */
7 #include <zebra.h>
8
9 #include "prefix.h"
10 #include "table.h"
11 #include "vrf.h"
12 #include "nexthop.h"
13 #include "srcdest_table.h"
14
15 #include "static_vrf.h"
16 #include "static_routes.h"
17 #include "static_zebra.h"
18 #include "static_nht.h"
19
20 static void static_nht_update_path(struct static_path *pn, struct prefix *nhp,
21 uint32_t nh_num, vrf_id_t nh_vrf_id,
22 struct vrf *vrf)
23 {
24 struct static_nexthop *nh;
25
26 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
27 if (nh->nh_vrf_id != nh_vrf_id)
28 continue;
29
30 if (nh->type != STATIC_IPV4_GATEWAY
31 && nh->type != STATIC_IPV4_GATEWAY_IFNAME
32 && nh->type != STATIC_IPV6_GATEWAY
33 && nh->type != STATIC_IPV6_GATEWAY_IFNAME)
34 continue;
35
36 if (nhp->family == AF_INET
37 && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr)
38 nh->nh_valid = !!nh_num;
39
40 if (nhp->family == AF_INET6
41 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, IPV6_MAX_BYTELEN)
42 == 0)
43 nh->nh_valid = !!nh_num;
44
45 if (nh->state == STATIC_START)
46 static_zebra_route_add(pn, true);
47 }
48 }
49
50 static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
51 uint32_t nh_num, afi_t afi, safi_t safi,
52 struct vrf *vrf, vrf_id_t nh_vrf_id)
53 {
54 struct route_table *stable;
55 struct static_vrf *svrf;
56 struct route_node *rn;
57 struct static_path *pn;
58 struct static_route_info *si;
59
60 svrf = vrf->info;
61 if (!svrf)
62 return;
63
64 stable = static_vrf_static_table(afi, safi, svrf);
65 if (!stable)
66 return;
67
68 if (sp) {
69 rn = srcdest_rnode_lookup(stable, sp, NULL);
70 if (rn && rn->info) {
71 si = static_route_info_from_rnode(rn);
72 frr_each(static_path_list, &si->path_list, pn) {
73 static_nht_update_path(pn, nhp, nh_num,
74 nh_vrf_id, vrf);
75 }
76 route_unlock_node(rn);
77 }
78 return;
79 }
80
81 for (rn = route_top(stable); rn; rn = route_next(rn)) {
82 si = static_route_info_from_rnode(rn);
83 if (!si)
84 continue;
85 frr_each(static_path_list, &si->path_list, pn) {
86 static_nht_update_path(pn, nhp, nh_num, nh_vrf_id, vrf);
87 }
88 }
89 }
90
91 void static_nht_update(struct prefix *sp, struct prefix *nhp, uint32_t nh_num,
92 afi_t afi, safi_t safi, vrf_id_t nh_vrf_id)
93 {
94
95 struct vrf *vrf;
96
97 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
98 static_nht_update_safi(sp, nhp, nh_num, afi, safi, vrf,
99 nh_vrf_id);
100 }
101
102 static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
103 safi_t safi, struct vrf *vrf,
104 vrf_id_t nh_vrf_id)
105 {
106 struct static_vrf *svrf;
107 struct route_table *stable;
108 struct static_nexthop *nh;
109 struct static_path *pn;
110 struct route_node *rn;
111 struct static_route_info *si;
112
113 svrf = vrf->info;
114 if (!svrf)
115 return;
116
117 stable = static_vrf_static_table(afi, safi, svrf);
118 if (!stable)
119 return;
120
121 for (rn = route_top(stable); rn; rn = route_next(rn)) {
122 si = static_route_info_from_rnode(rn);
123 if (!si)
124 continue;
125 frr_each(static_path_list, &si->path_list, pn) {
126 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
127 if (nh->nh_vrf_id != nh_vrf_id)
128 continue;
129
130 if (nhp->family == AF_INET
131 && nhp->u.prefix4.s_addr
132 != nh->addr.ipv4.s_addr)
133 continue;
134
135 if (nhp->family == AF_INET6
136 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6,
137 16)
138 != 0)
139 continue;
140
141 /*
142 * We've been told that a nexthop we
143 * depend on has changed in some manner,
144 * so reset the state machine to allow
145 * us to start over.
146 */
147 nh->state = STATIC_START;
148 }
149 }
150 }
151 }
152
153 void static_nht_reset_start(struct prefix *nhp, afi_t afi, safi_t safi,
154 vrf_id_t nh_vrf_id)
155 {
156 struct vrf *vrf;
157
158 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
159 static_nht_reset_start_safi(nhp, afi, safi, vrf, nh_vrf_id);
160 }
161
162 static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
163 safi_t safi, struct vrf *vrf,
164 enum static_install_states state)
165 {
166 struct static_vrf *svrf;
167 struct route_table *stable;
168 struct route_node *rn;
169 struct static_nexthop *nh;
170 struct static_path *pn;
171 struct static_route_info *si;
172
173 svrf = vrf->info;
174 if (!svrf)
175 return;
176
177 stable = static_vrf_static_table(afi, safi, svrf);
178 if (!stable)
179 return;
180
181 rn = srcdest_rnode_lookup(stable, sp, NULL);
182 if (!rn)
183 return;
184 si = rn->info;
185 if (si) {
186 frr_each(static_path_list, &si->path_list, pn) {
187 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
188 nh->state = state;
189 }
190 }
191 }
192
193 route_unlock_node(rn);
194 }
195
196 void static_nht_mark_state(struct prefix *sp, safi_t safi, vrf_id_t vrf_id,
197 enum static_install_states state)
198 {
199 struct vrf *vrf;
200
201 afi_t afi = AFI_IP;
202
203 if (sp->family == AF_INET6)
204 afi = AFI_IP6;
205
206 vrf = vrf_lookup_by_id(vrf_id);
207 if (!vrf || !vrf->info)
208 return;
209
210 static_nht_mark_state_safi(sp, afi, safi, vrf, state);
211 }