]>
Commit | Line | Data |
---|---|---|
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 | 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) | |
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 | ||
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; | |
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 |
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) | |
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 | |
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; | |
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 | ||
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; | |
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 | ||
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 | } |