]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_nht.c
Merge pull request #6435 from idryzhov/fix-no-vrf
[mirror_frr.git] / staticd / static_nht.c
1 /*
2 * Static NHT code.
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
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.
10 *
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.
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"
26 #include "srcdest_table.h"
27
28 #include "static_vrf.h"
29 #include "static_routes.h"
30 #include "static_zebra.h"
31 #include "static_nht.h"
32
33 static 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)
37 {
38 struct static_nexthop *nh;
39
40 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
41 if (nh->nh_vrf_id != nh_vrf_id)
42 continue;
43
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)
48 continue;
49
50 if (nhp->family == AF_INET
51 && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr)
52 nh->nh_valid = !!nh_num;
53
54 if (nhp->family == AF_INET6
55 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, 16) == 0)
56 nh->nh_valid = !!nh_num;
57
58 if (nh->state == STATIC_START)
59 static_zebra_route_add(rn, pn, safi, true);
60 }
61 }
62
63 static 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;
68 struct static_vrf *svrf;
69 struct route_node *rn;
70 struct static_path *pn;
71 struct static_route_info *si;
72
73 svrf = vrf->info;
74 if (!svrf)
75 return;
76
77 stable = static_vrf_static_table(afi, safi, svrf);
78 if (!stable)
79 return;
80
81 if (sp) {
82 rn = srcdest_rnode_lookup(stable, sp, NULL);
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 }
89 route_unlock_node(rn);
90 }
91 return;
92 }
93
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 }
103 }
104
105 void static_nht_update(struct prefix *sp, struct prefix *nhp,
106 uint32_t nh_num, afi_t afi, vrf_id_t nh_vrf_id)
107 {
108
109 struct vrf *vrf;
110
111 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
112 static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_UNICAST,
113 vrf, nh_vrf_id);
114 static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_MULTICAST,
115 vrf, nh_vrf_id);
116 }
117 }
118
119 static 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;
125 struct static_nexthop *nh;
126 struct static_path *pn;
127 struct route_node *rn;
128 struct static_route_info *si;
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)) {
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 }
166 }
167 }
168 }
169
170 void 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
182 static 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;
188 struct route_node *rn;
189 struct static_nexthop *nh;
190 struct static_path *pn;
191 struct static_route_info *si;
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;
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 }
212
213 route_unlock_node(rn);
214 }
215
216 void 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 }