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